在没有被要求的情况下进行呼叫 bison -y

发布于 2024-10-25 20:40:05 字数 7362 浏览 6 评论 0原文

我正在编写一个语法,名为 portugol。文件名很基本,但我选择将我的 C 程序命名为 portugol.c

所以,基本上,我必须这样做:(

flex portugol.l      ==> lex.yy.c
bison -dy portugol.y ==> y.tab.c and y.tab.h
gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly  ==> portugol.bin

我也有 portugol.h,但它与问题无关)

很长一段时间以来,我使用一个名为 flexyagcc.sh 的 shell 脚本做这个。过程中没有错误。

所以现在我决定学习makefile

我面临的问题是,由于某种奇怪的原因,我调用的“bison -dy”后面跟着我没有写的命令:mv -f y.tab.c portugol .c

好吧,这破坏了我手工制作的源文件!

我已经尽了一切努力,但无法摆脱这个“mv”。

我什至睡了一会儿并尝试:

y.tab.c y.tab.h : portugol.y
    @echo --- bison -----------------------------------------------
    mv -f portugol.c ptg.c
    $(BISON) $(BFLAGS) portugol.y
    @echo --- bison sleeping --------------------------------------
    sleep 5
    -mv -f portugol.c y.tab.c
    -mv -f ptg.c portugol.c

但令我惊讶的是,我收到了以下事件(按此顺序):

$ make all o=pequeno
--- bison -----------------------------------------------
mv -f portugol.c ptg.c
bison -dy portugol.y
--- bison sleeping --------------------------------------
sleep 5
mv -f portugol.c y.tab.c
mv: cannot stat `portugol.c': No such file or directory
make: [y.tab.c] Error 1 (ignored)
mv -f ptg.c portugol.c
bison -dy portugol.y 
mv -f y.tab.c portugol.c

惊喜! mv 命令是最后一个!不管我做什么。我创建了其他规则,只是为了让它最后发生(或者首先欺骗递归过程)。决不!我还使用了指令: .NOTPARALLEL. 没办法。

我还尝试在同一行中执行所有操作,以确保它们按给定的顺序执行:

mv -f portugol.c ptg.c && $(BISON) $(BFLAGS) portugol.y && sleep 5 && mv -f portugol.c y.tab.c && mv -f ptg.c portugol.c

没有成功。

好吧,在我放弃之前,我决定使用标准的 bison 输出。所以,我会:

flex portugol.l         ==> lex.yy.c
bison -d portugol.y     ==> portugol.tab.c and y.tab.h
gcc portugol.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly  ==> portugol.bin

但我仍然得到这个:

--- bison -----------------------------------------------
bison -d portugol.y
bison -y portugol.y 
mv -f y.tab.c portugol.c

我还尝试在野牛之前和之后尝试 chmod -w+w ,没门。

现在,我已经没有想法了。

有没有办法阻止 make 调用第二个野牛?或者调用mv命令?或者欺骗它不覆盖我的文件 portugol.c

谢谢! Beco

PS-编辑。使用:

 Ubuntu 10.04.2 LTS
 GNU Make 3.81

PPS。已编辑。小错别字。

购买力平价。已编辑。回答 伊势紫藤:

谢谢您的回答。我已将您的 makefile 保存为 makefile2 并尝试过。我从make得到的答案是:

$ make -f makefile2
bison -dy portugol.y
yacc  portugol.y 
mv -f y.tab.c portugol.c
gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly
gcc: y.tab.c: No such file or directory
make: *** [portugol.bin] Error 1

我还注意到“今天”第二个bison调用不是bison调用,而是yacc调用。也许我们在这里谈论一些环境变量?它也随着我的 makefile 的变化而变化:

$ make all o=pequeno
--- bison -----------------------------------------------
bison --defines=y.tab.h --output=y.tab.c portugol.y
--- flex ------------------------------------------------
flex  portugol.l
yacc  portugol.y 
mv -f y.tab.c portugol.c

PPPPS。回答贝塔。你的建议有效。我调用了 make y.tab.c 并得到了一个简单的:

$ make y.tab.c
--- bison -----------------------------------------------
bison --defines=y.tab.h --output=y.tab.c portugol.y
$

这是我完整的 makefile:

# Compila o compilador Portugol usando lex e yacc,
# e opcionalmente gera o .asm.c e o .bin
# a partir do fonte .ptg usando o novo compilador gerado.
#
#/*
#    arquivo: makefile
#    Autor: Ruben Carlo Benante
#    Email: ***@beco.cc
#    Data: 23/04/2009
#    Modificado: 22/03/2011
#    Versao: Portugol v3q
#*/
#
# Exemplo:
# ./flexyagcc portugol teste
#
# inicia os seguintes processos:
#      flex portugol.l                                          (gera lex.yy.c)
#      bison -dy portugol.y                                     (gera yy.tab.c e yy.tab.h)
#      gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly  (gera portugol.bin)
#
# inicia opcionalmente (ultimas linhas descomentadas):
#      portugol.bin teste.ptg teste.asm.c                (gera teste.asm.c)
#      gcc -x c teste.asm.c -o teste.bin -lm             (gera teste.bin)
#
#
# entrada:
#          portugol.l (arquivo em linguagem lex, analisador lexico)
#          portugol.y (arquivo em linguagem yacc, analisador sintatico)
#          portugol.c (arquivo em linguagem c, gerador de codigo)
# entrada opcional:
#          teste.ptg  (arquivo em linguagem portugol)
#
# saida:
#        lex.yy.c (saida do lex, em linguagem c)
#        y.tab.c  (saida do yacc, em linguagem c)
#        y.tab.h  (saida do yacc, definicoes da linguagem portugol)
#        portugol.bin (saida do gcc, arquivo executavel, finalmente o compilador portugol)
# saida opcional:
#        teste.asm.c   (saida do compilador portugol, arquivo em codigo de quadruplas)
#        teste.bin     (saida do gcc, arquivo executavel, o fonte .ptg em binario)
#
###################################### 
LEX     = flex
BISON = bison
BFLAGS  = --defines=y.tab.h --output=y.tab.c
CC = gcc
#CFLAGS = -g0 -O3 -Wall
CFLAGS = -g0
OBJS = y.tab.o lex.yy.o portugol.o
#OBJS = portugol.tab.o lex.yy.o portugol.o
DEPS =  portugol.h y.tab.h
SOURCES = y.tab.c lex.yy.c portugol.c
#SOURCES = portugol.tab.c lex.yy.c portugol.c

.PHONY : clean cleanall cleanptg run all makebug teste

.NOTPARALLEL :

#portugol.bin : lex.yy.c y.tab.c y.tab.h portugol.c portugol.h
portugol.bin : $(SOURCES) $(DEPS) $(OBJS)
    @echo --- gcc portugol ----------------------------------------
    $(CC) $(CFLAGS) $(OBJS) -o portugol.bin -lm -ly
#   gcc lex.yy.c y.tab.c portugol.c -o portugol.bin -lm -ly
#   $(CC) $(CFLAGS) $(SOURCES) -o portugol.bin -lm -ly

%.o : %.c
    @echo --- gcc objects -----------------------------------------
    $(CC) $(CFLAGS) -c $< -o $@

#portugol.tab.c y.tab.h : portugol.y
y.tab.c y.tab.h : portugol.y
    @echo --- bison -----------------------------------------------
    $(BISON) $(BFLAGS) portugol.y
#   @echo --- bison y.tab.c ---------------------------------------
#   mv -f portugol.c ptg.c
#   sleep 3
#   -mv -f portugol.c y.tab.c
#   -mv -f ptg.c portugol.c

lex.yy.c : portugol.l
    @echo --- flex ------------------------------------------------
    $(LEX) $(LFLAGS) portugol.l

teste :
    @echo --- testing ---------------------------------------------
    @echo $(o)

#Portugol -----------

%.asm.c : %.ptg portugol.bin
    @echo --- portugol --------------------------------------------
    ./portugol.bin $< $@

%.bin : %.asm.c
    @echo --- gcc asm ---------------------------------------------
    $(CC) -x c $< -o $@ -lm

run : $(o).bin
    @echo --- running! --------------------------------------------
    ./$(o).bin

all : $(o).bin

clean:
    -rm lex.yy.c y.tab.c y.tab.h *.o portugol.bin portugol.tab.c

cleanall:
    -rm lex.yy.c y.tab.c y.tab.h *.o *.bin

cleanasm:
    -rm *.asm.c

VPS。重要编辑更新。注意真正问题的可能指示:

我将名称 portugol.y 更改为 portugol.syn 并且问题已经停止!

--- bison -----------------------------------------------
bison --defines=y.tab.h --output=y.tab.c portugol.syn
---------------------------------------------------------

怎么样?在我看来,这表明 make 对文件“.y”有一些默认评估,现在我们需要回答这个问题,找出其根源,以及如何禁用它。非常感谢。

I have a grammar I'm writing, called portugol. The files names are basic, but I chose to call my c program portugol.c.

So, basically, I have to do:

flex portugol.l      ==> lex.yy.c
bison -dy portugol.y ==> y.tab.c and y.tab.h
gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly  ==> portugol.bin

(I also have portugol.h, but it is irrelevant to the problem)

For long time now, I'm using a shell script I called flexyagcc.sh that do this. No error in the process.

So now I decided to learn makefile.

The problem I'm facing is that for some odd reason, "bison -dy" I called is followed by this command I didn't write: mv -f y.tab.c portugol.c

Well, this destroys my handmade source file!

I've tried all I could, but could not get rid of this "mv".

I even did a sleep and tried:

y.tab.c y.tab.h : portugol.y
    @echo --- bison -----------------------------------------------
    mv -f portugol.c ptg.c
    $(BISON) $(BFLAGS) portugol.y
    @echo --- bison sleeping --------------------------------------
    sleep 5
    -mv -f portugol.c y.tab.c
    -mv -f ptg.c portugol.c

But for my surprise, I got the following events (in this order):

$ make all o=pequeno
--- bison -----------------------------------------------
mv -f portugol.c ptg.c
bison -dy portugol.y
--- bison sleeping --------------------------------------
sleep 5
mv -f portugol.c y.tab.c
mv: cannot stat `portugol.c': No such file or directory
make: [y.tab.c] Error 1 (ignored)
mv -f ptg.c portugol.c
bison -dy portugol.y 
mv -f y.tab.c portugol.c

Surprise! The mv command is the last one! No matter what I do. I created other rules, just to make it happen last (or first to trick the recursive process). No way! I also used the directive: .NOTPARALLEL. No way.

I also tried all in the same line, to be sure they execute in the given order:

mv -f portugol.c ptg.c && $(BISON) $(BFLAGS) portugol.y && sleep 5 && mv -f portugol.c y.tab.c && mv -f ptg.c portugol.c

No success.

Well, before I gave up, I decided to use the standard bison output. So, I would have:

flex portugol.l         ==> lex.yy.c
bison -d portugol.y     ==> portugol.tab.c and y.tab.h
gcc portugol.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly  ==> portugol.bin

But I still get this:

--- bison -----------------------------------------------
bison -d portugol.y
bison -y portugol.y 
mv -f y.tab.c portugol.c

I also tried to chmod -w before and +w after bison, no way.

For now, I run out of ideas.

Is there a way to prevent make to call the second bison? Or to call the mv command? Or to trick it to not overwrite my file portugol.c?

Thanks!
Beco

PS- Edited. Using:

 Ubuntu 10.04.2 LTS
 GNU Make 3.81

PPS. Edited. Minor typos.

PPPS. Edited. Answering Ise wisteria:

Thanks for your answer. I've saved your makefile as makefile2 and tried. The answer I got from the make is:

$ make -f makefile2
bison -dy portugol.y
yacc  portugol.y 
mv -f y.tab.c portugol.c
gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly
gcc: y.tab.c: No such file or directory
make: *** [portugol.bin] Error 1

I also noted that "today" the second bison call is not a bison call, but a yacc call. Maybe we are talking about some environment variable here? It also changes with my makefile:

$ make all o=pequeno
--- bison -----------------------------------------------
bison --defines=y.tab.h --output=y.tab.c portugol.y
--- flex ------------------------------------------------
flex  portugol.l
yacc  portugol.y 
mv -f y.tab.c portugol.c

PPPPS. Answering Beta. Your advice works. I called make y.tab.c and got a simple:

$ make y.tab.c
--- bison -----------------------------------------------
bison --defines=y.tab.h --output=y.tab.c portugol.y
$

Here is my complete makefile:

# Compila o compilador Portugol usando lex e yacc,
# e opcionalmente gera o .asm.c e o .bin
# a partir do fonte .ptg usando o novo compilador gerado.
#
#/*
#    arquivo: makefile
#    Autor: Ruben Carlo Benante
#    Email: ***@beco.cc
#    Data: 23/04/2009
#    Modificado: 22/03/2011
#    Versao: Portugol v3q
#*/
#
# Exemplo:
# ./flexyagcc portugol teste
#
# inicia os seguintes processos:
#      flex portugol.l                                          (gera lex.yy.c)
#      bison -dy portugol.y                                     (gera yy.tab.c e yy.tab.h)
#      gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly  (gera portugol.bin)
#
# inicia opcionalmente (ultimas linhas descomentadas):
#      portugol.bin teste.ptg teste.asm.c                (gera teste.asm.c)
#      gcc -x c teste.asm.c -o teste.bin -lm             (gera teste.bin)
#
#
# entrada:
#          portugol.l (arquivo em linguagem lex, analisador lexico)
#          portugol.y (arquivo em linguagem yacc, analisador sintatico)
#          portugol.c (arquivo em linguagem c, gerador de codigo)
# entrada opcional:
#          teste.ptg  (arquivo em linguagem portugol)
#
# saida:
#        lex.yy.c (saida do lex, em linguagem c)
#        y.tab.c  (saida do yacc, em linguagem c)
#        y.tab.h  (saida do yacc, definicoes da linguagem portugol)
#        portugol.bin (saida do gcc, arquivo executavel, finalmente o compilador portugol)
# saida opcional:
#        teste.asm.c   (saida do compilador portugol, arquivo em codigo de quadruplas)
#        teste.bin     (saida do gcc, arquivo executavel, o fonte .ptg em binario)
#
###################################### 
LEX     = flex
BISON = bison
BFLAGS  = --defines=y.tab.h --output=y.tab.c
CC = gcc
#CFLAGS = -g0 -O3 -Wall
CFLAGS = -g0
OBJS = y.tab.o lex.yy.o portugol.o
#OBJS = portugol.tab.o lex.yy.o portugol.o
DEPS =  portugol.h y.tab.h
SOURCES = y.tab.c lex.yy.c portugol.c
#SOURCES = portugol.tab.c lex.yy.c portugol.c

.PHONY : clean cleanall cleanptg run all makebug teste

.NOTPARALLEL :

#portugol.bin : lex.yy.c y.tab.c y.tab.h portugol.c portugol.h
portugol.bin : $(SOURCES) $(DEPS) $(OBJS)
    @echo --- gcc portugol ----------------------------------------
    $(CC) $(CFLAGS) $(OBJS) -o portugol.bin -lm -ly
#   gcc lex.yy.c y.tab.c portugol.c -o portugol.bin -lm -ly
#   $(CC) $(CFLAGS) $(SOURCES) -o portugol.bin -lm -ly

%.o : %.c
    @echo --- gcc objects -----------------------------------------
    $(CC) $(CFLAGS) -c 
lt; -o $@

#portugol.tab.c y.tab.h : portugol.y
y.tab.c y.tab.h : portugol.y
    @echo --- bison -----------------------------------------------
    $(BISON) $(BFLAGS) portugol.y
#   @echo --- bison y.tab.c ---------------------------------------
#   mv -f portugol.c ptg.c
#   sleep 3
#   -mv -f portugol.c y.tab.c
#   -mv -f ptg.c portugol.c

lex.yy.c : portugol.l
    @echo --- flex ------------------------------------------------
    $(LEX) $(LFLAGS) portugol.l

teste :
    @echo --- testing ---------------------------------------------
    @echo $(o)

#Portugol -----------

%.asm.c : %.ptg portugol.bin
    @echo --- portugol --------------------------------------------
    ./portugol.bin 
lt; $@

%.bin : %.asm.c
    @echo --- gcc asm ---------------------------------------------
    $(CC) -x c 
lt; -o $@ -lm

run : $(o).bin
    @echo --- running! --------------------------------------------
    ./$(o).bin

all : $(o).bin

clean:
    -rm lex.yy.c y.tab.c y.tab.h *.o portugol.bin portugol.tab.c

cleanall:
    -rm lex.yy.c y.tab.c y.tab.h *.o *.bin

cleanasm:
    -rm *.asm.c

VPS. Important edit update. Attention for a possible indication of the real problem:

I changed the name portugol.y to portugol.syn and the problem has stoped!

--- bison -----------------------------------------------
bison --defines=y.tab.h --output=y.tab.c portugol.syn
---------------------------------------------------------

How is that? This indicates, in my opinion, that make has some default evaluation for files ".y" and now we need, to answer this question, to find out the root of this, and how to disable it. Thanks very much.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

森林迷了鹿 2024-11-01 20:40:05

问题是 make 具有从 .y 和 .l 文件构建 .c 文件的内置规则,正是这些内置规则被触发并导致您悲伤。

使用 GNU make,您可以通过用空白规则覆盖这些内置规则来禁用它们。将

%.c: %.y
%.c: %.l

你的 makefile 放在某个地方,你的问题就会消失。

您可以通过运行 make -p -f /dev/null 来查看 GNU make 的所有内置规则

The problem is that make has built-in rules for building .c files from .y and .l files, and it is these builtin rules that are getting triggered and causing you grief.

With GNU make, you can disable these builtin rules by overriding them with blank rules. Put

%.c: %.y
%.c: %.l

in your makefile somewhere and your problems should go away.

You can see all of GNU make's built-in rules by running make -p -f /dev/null

羅雙樹 2024-11-01 20:40:05

基本上,不要试图对抗系统。您需要能够创建 portugol.o - 并拥有三个可能的源文件:portugol.lportugol.yportugol.c。这至少多了两个。

确保源文件的基本名称(减去扩展名)是唯一的。例如,使用 portugoll.lportugoly.yportugol.c 以及目标文件 portugoll.o >、portugoly.oportugol.o。或者使用更长的后缀 - portugol-lex.lportugol-yacc.y。或者portlex.lportyacc.y 或...

Basically, do not try to fight the system. You need to be able to create portugol.o - and have three possible source files: portugol.l, portugol.y, portugol.c. That is at least two too many.

Make sure that the basenames of the source files (minus the extension) are unique. For example, use portugoll.l, portugoly.y, and portugol.c, with object files portugoll.o, portugoly.o and portugol.o. Or use longer suffixes - portugol-lex.l, portugol-yacc.y. Or portlex.l, portyacc.y, or ...

寒江雪… 2024-11-01 20:40:05

谢谢乔纳森,

所以你看到了我也意识到的一个解决方案:更改文件名。但是,这就是问题的重点。我使用该脚本没有任何问题。如果我从 shell 脚本 flexyagcc.sh 调用 bison -dy portugol.y ,它会给我 y.tab.cy .tab.h。为什么不从 makefile 开始,这就是中心点!

我确实喜欢我的文件名,它使一切变得如此连贯:portugol.c:手工例程,portugol.h:头文件,portugol.l:lex 扫描器和 portugol.y:解析器。另外,这不是我今天做的项目,多年来一直如此,有很多版本(现在是 3.0)。因此,无法更改文件名。除此之外,无论如何我最终都会得到portugol.c!但这将是一个从 bison 自动生成的文件,又名 y.tab.c。因此,停止使用 portugol.c 来进行手工例程并开始使用相同的名称来进行解析器是非常令人困惑的。

我只想知道 makefile 发生了什么,以及如何使用它来按原样替换脚本。不幸的是,虽然我不能,但我将使用该脚本。该脚本非常简单:

flex portugol.l
bison -dy portugol.y
gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly

看,我什至懒得拥有目标 portugol.oy.tab.olex.yy.o。我直接在源代码上运行 gcc 来跳过创建它们。如果在第一次尝试销毁我的 portugol.c 后,我手动将创建的文件重命名为 y.tab.c,我也可以在 makefile 中执行此操作。

所以问题是 makefile 与上面的脚本不同,它尝试创建以下内容:

  • lex the same: portugol.l 对于两种情况(脚本和 makefile)
  • bison: 自动从 y 更改。 tab.cportugol.c (这里是问题!)
  • c 代码:我需要将 portugol.c 更改为其他内容,例如 portugol-funcs.c

感谢您的关注!
贝科

Thank you Jonathan,

So you see the one solution I've also perceived: change the name of the file. But, well, that is the point of the question. I have no problems using the script. If I call bison -dy portugol.y from the shell script flexyagcc.sh it gives me y.tab.c and y.tab.h. Why not from a makefile, that is the central point!

I do like my file names, it makes all so coherent: portugol.c: handmade routines, portugol.h:header file, portugol.l:lex scanner, and portugol.y: parser. Also, this is not a project I made today, it has being like that for years now, lots of versions (now 3.0). So, it is not an option to change the file names. Beside that, I would end up with portugol.c anyway! But it would be a file automatically generated from bison, aka y.tab.c. So, it is very confusing to stop using portugol.c to have handmade routines, and start using the same name to have the parser.

I just want to know what is happening with makefile, and how can I use it to substitute the script the way it is. While I can't, unfortunately, I'll be using the script. The script is very simple:

flex portugol.l
bison -dy portugol.y
gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly

See, I don't even bother to have the objectives portugol.o, y.tab.o and lex.yy.o. I skip creating them by just running the gcc on the sources directly. I also can do this in the makefile, if after the first attempt to destroy my portugol.c, I rename manually the file created to be y.tab.c.

So the problem is that makefile differs from the above script by attempting to create the following:

  • lex the same: portugol.l for both cases (script and makefile)
  • bison: automagically changed from y.tab.c to portugol.c (here the problem!)
  • c code: I would need to change portugol.c to something else, like portugol-funcs.c

Thanks for your kind attention!
Beco

随波逐流 2024-11-01 20:40:05

奇怪的是,据我用小型临时文件进行测试,您遇到的问题是
提到的没有发生。
我的 make 版本是 GNU 3.80。
供您参考,以下是我使用的 makefile

portugol.bin: y.tab.c lex.yy.c portugol.c
        gcc $^ -o $@ -lm -ly

y.tab.c: portugol.y
        bison -dy 
lt;

lex.yy.c: portugol.l
        flex 
lt;

希望这有帮助

Strangely, as far as I tested with small improvised files, the problem you
mentioned didn't occur.
My make's version is GNU 3.80.
For your information, the following is the makefile I used.

portugol.bin: y.tab.c lex.yy.c portugol.c
        gcc $^ -o $@ -lm -ly

y.tab.c: portugol.y
        bison -dy 
lt;

lex.yy.c: portugol.l
        flex 
lt;

Hope this helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文