grok12
grok12

Reputation: 3676

gcc produces .o but bash says unknown command

Edit: I've fixed several things that were pointed out but the real problem remains unsolved.

This bash script:

set -vx

/usr/bin/llvm-gcc-4.2 -ansi -g -o mytest mytest.c 
ls -l mytest
./mytest
file mytest

produces this output:

/usr/bin/llvm-gcc-4.2 -ansi -g -o mytest mytest.c 
++ /usr/bin/llvm-gcc-4.2 -ansi -g -o mytest mytest.c
ls -l mytest
++ ls -l mytest
-rwxr-xr-x  1 jimslager  wheel  37496 May 27 17:26 mytest
./mytest
++ ./mytest
error: unknown command ./mytest
file mytest
++ file mytest
mytest: Mach-O 64-bit executable x86_64

I've extracted this out of something larger that I've been using for several months but have never seen a result like this. How can gcc produce an object with no errors or warnings but the object is unknown?

I'll post test.c if someone asks but it's long and my question seems to me to be independent of what's in test.c.

Edit: Here is the code. Sorry it is so long.

/* Test Exercise 5-10: Write the program myexpr, which evaluates a reverse Polish expression from the command line, where each operator or operand is a separate argument.  For example,
 *      expr 2 3 4 + *
 * evaluates 2 x (3+4).
 * */
#include <stdio.h>
#include <string.h>
#define MAXLINE 68
#define TABSIZE 8
#define TAB '`'
#define SPACE '-'
#define NEW '\\'
#define TRUE 1
#define FALSE 0
#define IN 1
#define OUT 0
#define FOLDLENGTH 20
#define MAXLEN 12
#define SMALLER(i, j) ((i) > (j) ? (j) : (i))
#define N(c) (c=='\0' ? '\\' : c)

/* #include "subs.c" */

#define MAXOP 100 /* max size of operand or operator */ 
#define NUMBER '0' /* signal that a number was found */

int getop(char []); 
void push(double); 
double pop(void);
double top(void);
void dup(void);
void clear(void);
void stackswap(void);
double atof(char s[]);
int myisdigit(char c);
int myisspace(char c);

/* reverse Polish calculator */ 
int main(int argc, char *argv[]) 
{
    int type; 
    double op2; 
    char s[MAXOP];

    while (--argc>0) 
        while (type = getop(&(*++argv[0])))
printf("Just after while: type = %d, *argv[0] = %s\n", type, *argv);
        switch (type) {
        case NUMBER: 
            push(atof(*argv));
printf("NUMBER: atof(*argv[0]) = %g, *argv[0] = %s\n", atof(*argv), *argv);
            break; 
        case '+':
printf("+ detected\n");
            push(pop() + pop());
            break; 
        case '*':
printf("* detected\n");
            push(pop() * pop()); 
            break; 
        case '-':
printf("- detected\n");
            op2 = pop(); 
            push(pop() - op2);
            break;
        case '/': 
printf("/ detected\n");
            op2 = pop();
            if (op2 != 0.0) 
                push(pop() / op2);
            else
                printf("error: zero divisor\n"); 
            break;
        case '%': 
printf("Modulo detected\n");
            op2 = pop();
            if (op2 != 0.0) 
                push((int) pop() % (int) op2);
            else
                printf("error: zero divisor\n"); 
            break;
        case 't':
printf("t detected\n");
            printf("%g\n", top());
            break; 
        case 'd':
printf("d detected\n");
            dup();

            break; 
        case 's': 
printf("s detected\n");
            stackswap();
            break;
        case 'c':
printf("c detected\n");
            clear();
            break;
        case '\n': 
printf("\\n detected\n");
            printf("\t%.8g\n", pop()); 
            break;
        default: 
            printf("error: unknown command %s\n", *argv); 
            break;
        }
     return 0;
}

#define MAXVAL 100 /* maximum depth of val stack */

int sp = 0; /* next free stack position */ 
double val[MAXVAL]; /* value stack */

/* push: push f onto value stack */ 
void push(double f) 
{
printf("push: Started.   f = %g, sp = %d\n", f, sp);
    if (sp < MAXVAL) 
        val[sp++] = f;
    else
        printf("error: stack full, can't push %g\n", f);
printf("push: Finished.  f = %g, sp = %d\n", f, sp);
}

/* dup: duplicate top of stack */ 
void dup(void) 
{
printf("dup: Started.   top = %g, sp = %d\n", top(), sp);
    push(top());
printf("dup: Finished.   top = %g, sp = %d\n", top(), sp);
}

/* pop: pop and return top value from stack */ 
double pop(void) 
{
printf("pop: sp = %d, val[--sp] = %g\n", sp, val[sp-1]);
    if (sp > 0) 
        return val[--sp];
    else { 
        printf("error: stack empty\n"); 
        return 0.0;
    }
}

/* top: return top value from stack without changing sp */ 
double top(void) 
{
printf("top: sp = %d, val[0] = %g\n", sp, val[0]);
    if (sp > 0) 
        return val[sp-1];
    else { 
        printf("error: stack empty\n"); 
        return 0.0;
    }
}

/* stackswap: swap the top 2 values in stack */
void stackswap(void)
{
printf("Starting stackswap: val[sp-1] = %g, val[sp-2] = %g\n", val[sp-1], val[sp-2]);
    double op2, op3;
    op2 = pop();
    op3 = pop();
    push(op2);
    push(op3);
printf("Finishing stackswap: val[sp-1] = %g, val[sp-2] = %g\n", val[sp-1], val[sp-2]);
}

/* clear: clear the stack */
void clear(void)
{
    sp = 0;
}

int getch(void); 
void ungetch(int);

/* getop: get next character or numeric operand */ 
int getop(char s[]) 
{
    int i, c;

    while ((s[0] = c = getch()) == ' ' || c == '\t')
        ;
    s[1] = '\0'; 
    if (!isdigit(c) && c != '.')
        return c; /* not a number */
    i = 0;
    if (isdigit(c)) /* collect integer part */ 
        while (isdigit(s[++i] = c = getch()))
            ;
    if (c=='.') /* collect fraction part */
        while (isdigit(s[++i] = c = getch())) ;
    s[i] = '\0'; 
    if (c != EOF)
        ungetch(c); 
    return NUMBER;
}

#define BUFSIZE 100

char buf[BUFSIZE];  /* buffer for ungetch */ 
int bufp = 0;   /* next free position in buf */

int getch(void) /* get a (possibly pushed-back) character */ 
{
    return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) /* push character back on input */ 
{
    if (bufp >= BUFSIZE) 
        printf("ungetch: too many characters\n");
    else
        buf[bufp++] = c;
}

/* atof: convert s to double */
double atof(char s[])
{
    double val, power, epower, d; 
    int i, j, sign, esign=0, eval;
printf("atof: s = %s\n", s);

    for (i = 0; myisspace(s[i]); i++); /* skip white space */

    sign = (s[i] == '-') ? -1 : 1; /* Determine sign and strip it */
    if (s[i] == '+' || s[i] == '-')
        i++; 

    for (val = 0.0; myisdigit(s[i]); i++) /* Determine value before dec point */
        val = 10.0 * val + (s[i] - '0'); 

    if (s[i] == '.')
        i++; 

    for (power = 1.0; myisdigit(s[i]); i++) { /* include value after dec */
        val = 10.0 * val + (s[i] - '0'); 
        power *= 10;            /* power is where . goes */
    } 

    if (s[i]=='e' || s[i]=='E') { /* Exponential form */

        esign = (s[++i]=='-') ? -1 : 1; /* Sign of exponent */
        if (s[i]=='+' || s[i]=='-')
            i++;

        for (epower=0.1, eval=0.0; myisdigit(s[i]); i++) { /* Determine exponent */
            eval = 10*eval + (s[i]-'0');
            epower *= 10;
        }
    }

    d = (sign*val / power);     /* Place dec point in mantissa */

    if (esign!=0) {         /* If exp form then adjust exponent */
        for (j=1; j<=eval; j++) {
            d = (esign==1 ? d*10.0 : d/10.0);
        }
    }
    return (d);
}

/* Determine is c is a digit */
int myisdigit(char c)
{
    if (c>='0' && c<='9') 
        return TRUE;
    else 
        return FALSE;
}

/* Returns 1 if c is whitespace, 0 otherwise */
int myisspace(char c)
{
    return ((c==' ' || c=='\n' || c=='\t') ? 1 : 0); 
}

Upvotes: 3

Views: 551

Answers (5)

grok12
grok12

Reputation: 3676

Doh! It finally occurred to me what is happening here. This program is exercise 5-10 from K&R which is to revise the Reverse Polish Calculator of page 76 to receive its input from the command line rather than from stdin. I was in the process of doing that when I got the "unknown command" message and thought it was coming from the compiler but it was actually coming from my own code!

Now I will go back and modify it to prefix all error messages with argv[0] (and use this from now on) so that this mistake will never happen again.

Upvotes: 0

rlibby
rlibby

Reputation: 6021

Probably the local directory is not in your path (nor do you want it to be). You should be able to run it with ./test.o. Also, the .o suffix here is strange. You have a dynamically linked executable file, not an object file. (Try file test.o.) On Unix those normally don't have an extension, on Windows they normally have the extension .exe.

Upvotes: 2

puzzle
puzzle

Reputation: 6131

Make the last line ./test.o and everything should work.

If you only supply the file name but not a path, then only the search paths will be taken into account, and your current working directory in most cases isn't part of them (or rather definitely not, in your example).

Upvotes: 4

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 799190

  1. . is not in $PATH, so you need to specify the path to the file. ./test.o

  2. .o files are usually not executable; they must be linked before they can be run. Although this is not the case here.

Upvotes: 3

matja
matja

Reputation: 4179

It should probably be ./test.o to run it. Generally, UNIX systems don't have "." (the current dir) in the PATH by default.

Also, the ".o" extension is slightly misleading, because that is convention for an intermediate object file, not a stand-alone executable like you have produced here.

Upvotes: 6

Related Questions