Tuesday, October 4, 2016

Utterly Bizaare Behavior From gcc

I wrote a really stupidly simple C program in support of my milling operations, and it appears that y1 as a float variable is in some way reserved.  (I thought I left reserved variable names with FORTRAN.)

I changed the y1 variable to a1, and everything now compiles instead of complaining that y1 is being redeclared.

Here's the make file, and the source files.

vhal.mak
====================
INCL=/home/sherline/vhal/.
CC=gcc
CFLAGS=-I$(INCL)
DEPS=vhal.h parseargs2.h

all: excavate gauges excring exccircle circle.ngc parseargs2.o flat.ngc testparseargs2 slope \
    slope.ngc xslot.ngc yslot.ngc slope.ngc

parseargs.o: parseargs.c vhal.h
    $(CC) -o $@ -c -g $<

parseargs2.o: parseargs2.c parseargs2.h vhal.mak
    $(CC) -o $@ -c -g $< -I$(INCL) $(CFlAGS)

testparseargs2: testparseargs2.c parseargs2.h parseargs2.o vhal.mak
    $(CC) -o $@ -g -lm testparseargs2.c parseargs2.o -I$(INCL) $(CFlAGS)
    chmod ugo+x $@

excavate: excavate.c vhal.h parseargs2.o vhal.mak
    $(CC) -o $@ -g -lm excavate.c parseargs2.o -I$(INCL) $(CFlAGS)
    chmod ugo+x $@

gauges: gauges.c vhal.h parseargs2.o vhal.mak
    $(CC) -o $@ -g -lm gauges.c parseargs2.o -I$(INCL) $(CFlAGS)
    chmod ugo+x $@

sexccircle: exccircle.c vhal.h parseargs2.o vhal.mak
    $(CC) -o $@ -g -lm exccircle.c parseargs2.o -I$(INCL) $(CFlAGS)
    chmod ugo+x $@

excring: excring.c vhal.h parseargs2.o vhal.mak
    $(CC) -o $@ -g -lm excring.c parseargs2.o -I$(INCL) $(CFlAGS)
    chmod ugo+x $@

slot: slot.c vhal.h parseargs2.o vhal.mak
    $(CC) -o $@ -g -lm $@.c parseargs2.o -I$(INCL)
    chmod ugo+x $@

slope: slope.c vhal.h parseargs2.o vhal.mak
    $(CC) -o $@ -g -lm $@.c parseargs2.o -I$(INCL)
    chmod ugo+x $@

xslot.ngc: slot vhal.mak
    ./slot -md 0.250 -f 1 -mof 4 -xs 0 -xe 1 -ys .375 -ye .625 -zs -0.0570 -ze -0.25 -zi 0.01 >xslot.ngc

yslot.ngc: slot vhal.mak
    ./slot -md 0.250 -f 4 -mof 4 -xs 0.375 -xe .625 -ys 0 -ye 1 -zs -0.570 -ze -0.25 -zi 0.0001 >yslot.ngc

flat.ngc: excavate vhal.mak
    ./excavate -md 0.5 -xs 0 -xe 2 -ys 0 -ye 2 -zs -0.25 -ze -0.30 -zi 0.005 -f 20 -mof 3.0 >flat.ngc

gauges.ngc: excavate vhal.mak
    ./gauges -md 0.25 -hx1 0.25 -hy1 0.25 -hx2 0.25 -hy2 2.01 -hx3 2.26 -hy3 2.26 -hx4 2.26 -hy4 0.25 -x1 .5 -y1 0.5 -x2 .5 -y2 2.01 -x3 2.01 -y3 1.36 -x4 0.5 -y4 2.26  >flat.ngc

slope.ngc: slope vhal.mak
    ./slope -md 0.50 -f 3 -xsl 80 -xsc 3 -xew 4.6 -ys -0.1 -ye 1.2 -zs 0.05 -ze -.16 -mof 3.0 >slope.ngc

circle.ngc: excring vhal.mak
    ./excring -md 0.250 -f 2 -mof 4.0 -d 0.0001 -cd 0.611 -ex 0.5 -xs 0.5 -ys 0.5 -zs 0.00 -zi 0.001 -ze -0.5 >circle.ngc


gauges.c
=========
// Cut 4 point figure.
#include
#include
#include
#include "parseargs2.h"
extern int parseArgs2(flagsStructType* flags, int flagsCount, char* flagBfr[]);
#include "vhal.h"
#define min(X, Y)  ((X) < (Y) ? (X) : (Y))

float     millRate = 50.0f;
float     millDiameter = 0.5f;
float     holex1, holey1, holex2, holey2, holex3, holey3, holex4, holey4;
float    x1;
float    a1;
float    x2, y2, x3, y3, x4, y4;
float    zStart, zEnd, zStep, feedRate;

flagsStructType flags[] =
{
        {"f", &millRate},
        {"hx1", &holex1},
        {"hy1", &holey1},
        {"hx2", &holex2},
        {"hy2", &holey2},
        {"hx3", &holex3},
        {"hy3", &holey3},
        {"hx4", &holex4},
        {"hy4", &holey4},
        {"x1", &x1},
        {"a1", &a1},
        {"x2", &x2},
        {"y2", &y2},
        {"x3", &x3},
        {"y3", &y3},
        {"x4", &x4},
        {"y4", &y4},
        {"md", &millDiameter},
        {"zs", &zStart},
        {"ze", &zEnd},
        {"zi", &zStep}
};
void prolog(float feedRate)
{
  printf("%c\ng01 g20 g40 g49 f%0.4f\n", '%', feedRate);
}

void epilog()
{
  printf("m2\n%%\n");
}

int main(int argc, char* argv[])
{
  int argNbr;
  int firstPass = 1;
  parseArgs2(flags, _CountOf_(flags), argv);
  prolog(NAVFEED);
  float millRadius = millDiameter/2.0f;
  // position to top of workpiece
  float z;
  // mill holes
  for (z=0.1f; z >-(zEnd); z-=zStep)
  {
      // position above hole
      printf("g00 x%0.4f y%0.4f z%0.4f f%0.4f\n", holex1, holey1, zStart, NAVFEED);
      // down to position; slowly drill or mill through
      printf("g00 z%0.4f f%0.4f\n", z, feedRate);
      // raise above surface
      printf("g00 z%0.4f f%0.4f", zStart, NAVFEED);
      // repeat for other holes
      printf("g00 x%0.4f y%0.4f z%0.4f f%0.4f\n", holex2, holey2, zStart, NAVFEED);
      printf("g00 z%0.4f f%0.4f\n", z, feedRate);
      printf("g00 z%0.4f f%0.4f", zStart, NAVFEED);
      printf("g00 x%0.4f y%0.4f z%0.4f f%0.4f\n", holex3, holey3, zStart, NAVFEED);
      printf("g00 z%0.4f f%0.4f\n", z, feedRate);
      printf("g00 z%0.4f f%0.4f", zStart, NAVFEED);
      printf("g00 x%0.4f y%0.4f z%0.4f f%0.4f\n", holex4, holey4, zStart, NAVFEED);
      printf("g00 z%0.4f f%0.4f\n", z, feedRate);
      printf("g00 z%0.4f f%0.4f", zStart, NAVFEED);
  };
  // position to first point to be cut out
  for(z=0.1f; z>-(zEnd); z-=zStep)
  {
      printf("g00 x%0.4f y%0.4f z%0.4f f%0.4f\n", x1+millRadius, a1+millRadius, z, NAVFEED);
      printf("g00 x%0.4f y%0.4f z%0.4f f%0.4f\n", x2+millRadius, y2-millRadius, z, feedRate);
      printf("g00 x%0.4f y%0.4f z%0.4f f%0.4f\n", x3-millRadius, y3-millRadius, z, feedRate);
      printf("g00 x%0.4f y%0.4f z%0.4f f%0.4f\n", x4-millRadius, y4+millRadius, z, feedRate);
      printf("g00 x%0.4f y%0.4f z%0.4f f%0.4f\n", x1+millRadius, a1+millRadius, z, feedRate);
  }
  printf("g00 x0 y0 z1.0 f%0.4f\n", NAVFEED);
  epilog();
   exit(0);
}
   

parsearg2.c

=================
/*
 * parseArgs2.h
 *
 *  Created on: Jul 3, 2016
 *      Author: clayton
 */

#ifndef PARSEARGS2_H_
#define PARSEARGS2_H_

typedef struct flagsTag
{
    char*     flag;    // flag to match
    float*    valueAddr;    // where the matching value goes
} flagsStructType;

#define _CountOf_(A) ((sizeof(A))/(sizeof(A[0])))
#endif /* PARSEARGS2_H_ */

parseArgs2.c (shouldn't matter, it compiles fine and the problem is not during link)
========
/*
 * parseargs2.c
 *
 *  Created on: Jul 3, 2016
 *      Author: clayton
 */
#include
#include
#include "parseargs2.h"
#define TRUE 1
#define FALSE 0
typedef int boolean;


int parseArgs2(flagsStructType* flags, int flagsCount, char* flagBfr[])
        {
            boolean match;
            const char* valueString;
            int argvIndex;    // index into flags array
            int exitCode = 0;
            int flagsIndex;

            argvIndex = 1;
            for(; exitCode == 0 && flagBfr[argvIndex] != NULL; )
            {
                if (*flagBfr[argvIndex] == '-')    // is this a flag?
                {
                    match = FALSE;    // have we matched an entry in flags?
                    for (flagsIndex = 0; !match && flagsIndex < flagsCount;
                            flagsIndex++)
                    {
                        char* parm = flagBfr[argvIndex]+1;
                        char* flag = flags[flagsIndex].flag;
                        if (0 == strcmp(parm, flag))
                        {
                            match = TRUE;
                            // get pointer to following value
                            int flagLength = 1+strlen(flags[flagsIndex].flag);
                            valueString = flagBfr[argvIndex+1];
                            sscanf(valueString, "%f", flags[flagsIndex].valueAddr);
                            argvIndex += 2;
                        }
                    }
                    if (!match)
                      {
                        fprintf(stderr, "invalid flag: %s\n",
                            flagBfr[argvIndex]);
                        exitCode = 4;
                      }
                }
                else
                {
                    fprintf(stderr, "invalid flag: %s\n", flagBfr[argvIndex]);
                    // Skip to next flag
                    argvIndex++;
                }
            }
        return(exitCode);
    };


5 comments:

  1. I've done a lot of C over the last 30 years, and that one is a mystery to me.

    ReplyDelete
  2. Looks like it's documented:

    """
    Outside strict ISO C mode (-ansi, -std=c89 or -std=c99), the functions _exit, alloca, bcmp, bzero, dcgettext, dgettext, dremf, dreml, drem, exp10f, exp10l, exp10, ffsll, ffsl, ffs, fprintf_unlocked, fputs_unlocked, gammaf, gammal, gamma, gettext, index, isascii, j0f, j0l, j0, j1f, j1l, j1, jnf, jnl, jn, mempcpy, pow10f, pow10l, pow10, printf_unlocked, rindex, scalbf, scalbl, scalb, signbit, signbitf, signbitl, significandf, significandl, significand, sincosf, sincosl, sincos, stpcpy, strdup, strfmon, toascii, y0f, y0l, y0, y1f, y1l, y1, ynf, ynl and yn may be handled as built-in functions. All these functions have corresponding versions prefixed with __builtin_, which may be used even in strict C89 mode. """

    https://gcc.gnu.org/onlinedocs/gcc-4.0.2/gcc/Other-Builtins.html#Other-Builtins

    and

    Function: double y1 (double x)
    Function: float y1f (float x)
    Function: long double y1l (long double x)
    Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

    y1 returns the Bessel function of the second kind of order 1 of x. It may signal underflow if x is too large. If x is negative, y1 signals a domain error; if it is zero, y1 signals overflow and returns -∞.

    http://www.gnu.org/software/libc/manual/html_node/Special-Functions.html

    ReplyDelete
  3. My guess is that the conflict is with the Bessel function y1. ("man 3 y1")

    I'm not sure how many years it's been since I thought about Bessel functions. At least forty.

    ReplyDelete
  4. Not quite sure what is going on...but is there a "y1" value declared in the "parse2args.h" header?

    ReplyDelete
  5. It appears that conflict with the bessel function is the issue. Glad I posted this, because I ran out of disk space this morning, and Eclipse zeroed out the gauges.c file above, but there's the text!

    ReplyDelete