I wrote a new Emacs primitive (macroexpand-once) and recompiled Emacs
Now (macroexpand-once) fails with "Symbol's function definition is void".
What do I do about this?
UPDATE: Here is the code:
DEFUN ("macroexpand-once", Fmacroexpand_once, Smacroexpand_once, 1, 2, 0,
doc: /* Return result of expanding macros at top level of FORM.
If FORM is not a macro call, it is returned unchanged.
Otherwise, the macro is expanded and the expansion is returned.
The second optional arg ENVIRONMENT specifies an environment of macro
definitions to shadow the loaded ones for use in file byte-compilation. */)
(Lisp_Object form, Lisp_Object environment)
{
/* With cleanups from Hallvard Furuseth. */
register Lisp_Object expander, sym, def, tem;
do
{
/* Come back here each time we expand a macro call,
in case it expands into another macro call. */
if (!CONSP (form))
break;
/* Set SYM, give DEF and TEM right values in case SYM is not a symbol. */
def = sym = XCAR (form);
tem = Qnil;
/* Trace symbols aliases to other symbols
until we get a symbol that is not an alias. */
while (SYMBOLP (def))
{
QUIT;
sym = def;
tem = Fassq (sym, environment);
if (NILP (tem))
{
def = XSYMBOL (sym)->function;
if (!EQ (def, Qunbound))
continue;
}
break;
}
/* Right now TEM is the result from SYM in ENVIRONMENT,
and if TEM is nil then DEF is SYM's function definition. */
if (NILP (tem))
{
/* SYM is not mentioned in ENVIRONMENT.
Look at its function definition. */
struct gcpro gcpro1;
GCPRO1 (form);
def = Fautoload_do_load (def, sym, Qmacro);
UNGCPRO;
if (EQ (def, Qunbound) || !CONSP (def))
/* Not defined or definition not suitable. */
break;
if (!EQ (XCAR (def), Qmacro))
break;
else expander = XCDR (def);
}
else
{
expander = XCDR (tem);
if (NILP (expander))
break;
}
{
Lisp_Object newform = apply1 (expander, XCDR (form));
if (EQ (form, newform))
break;
else
form = newform;
}
} while (0);
return form;
}
It is just the code of macroexpand, but with do-while(0) instead of while(1).
You need to call defsubr. Do a search for Smacroexpand to see what I mean.
Related
I want to analyze the if-else structure of the demo.c file through joern and try to write a script with scala, but I found that the running results of scala1 and scala2 are different (the scala1 and scala2 want to express the same meaning). The difference between them is that a function fun is defined in scala1 (actually I want to use this function to achieve other repeated functions), but the result is wrong. Why? Is the parameter type (Traversal [ControlStructure]) of function Fun passed incorrectly?
--------- demo.c ---------
#include <stdio.h>
int main () {
/* local variable definition */
int a = 100;
/* check the boolean condition */
if(a>10) {
if(a>100){
printf("a > 100");
}else{
printf("10<a<100");
}
}else if( a <= 10 && a > 0) {
printf("Value of a is 20\n" );
}else {
printf("None of the values is matching\n" );
}
printf("Exact value of a is: %d\n", a );
if ( x > 10 ) {
printf("111");
}else{
printf("222")
}
while(x++ < MAX) {
if(x!=0) {
int y = 2*x;
sink(y);
}
}
return 0;
}
--------scala script 1--------
open("demo")
def Outermost_layer_branch =
cpg.method("main").block.astChildren.isControlStructure.controlStructureType("IF")
def fun(node:Traversal[ControlStructure]){
def node1 = node.astChildren.isControlStructure.controlStructureType("ELSE")
println(node1.size)
// the result is 1, it's right
def node2 =
node1.astChildren.filter(_.isBlock).astChildren.isControlStructure.controlStructureType("IF")
println(node2.size)
//the result is 0, it's wrong!!
}
fun(Outermost_layer_branch.order(3))
--------scala 2--------
open("demo")
def Outermost_layer_branch=
cpg.method("main").block.astChildren.isControlStructure.controlStructureType("IF")
def node1 = Outermost_layer_branch.order(3).astChildren.isControlStructure.controlStructureType("ELSE")
println(node1.size)
// the result is 1,and it is right!
def node2 = node1.astChildren.filter(_.isBlock).astChildren.isControlStructure.controlStructureType("IF")
println(node2.size)
// the result is 1,and it is right!
If I want to achieve the correct results through scala1, how can I pass parameters? Or is there any other way?
I want to analyze the if-else structure of the demo.c file through joern and try to write a script with scala, but I found that the running results of scala1 and scala2 are different (the scala1 and scala2 want to express the same meaning). The difference between them is that a function fun is defined in scala1 (actually I want to use this function to achieve other repeated functions), but the result is wrong. Why? Is the parameter type (Traversal [ControlStructure]) of function Fun passed incorrectly?
--------- demo.c ---------
#include <stdio.h>
int main () {
/* local variable definition */
int a = 100;
/* check the boolean condition */
if(a>10) {
if(a>100){
printf("a > 100");
}else{
printf("10<a<100");
}
}else if( a <= 10 && a > 0) {
printf("Value of a is 20\n" );
}else {
printf("None of the values is matching\n" );
}
printf("Exact value of a is: %d\n", a );
if ( x > 10 ) {
printf("111");
}else{
printf("222")
}
while(x++ < MAX) {
if(x!=0) {
int y = 2*x;
sink(y);
}
}
return 0;
}
--------scala script 1--------
open("demo")
def Outermost_layer_branch =
cpg.method("main").block.astChildren.isControlStructure.controlStructureType("IF")
def fun(node:Traversal[ControlStructure]){
def node1 = node.astChildren.isControlStructure.controlStructureType("ELSE")
println(node1.size)
// the result is 1, it's right
def node2 =
node1.astChildren.filter(_.isBlock).astChildren.isControlStructure.controlStructureType("IF")
println(node2.size)
//the result is 0, it's wrong!!
}
fun(Outermost_layer_branch.order(3))
--------scala 2--------
open("demo")
def Outermost_layer_branch=
cpg.method("main").block.astChildren.isControlStructure.controlStructureType("IF")
def node1 = Outermost_layer_branch.order(3).astChildren.isControlStructure.controlStructureType("ELSE")
println(node1.size)
// the result is 1,and it is right!
def node2 = node1.astChildren.filter(_.isBlock).astChildren.isControlStructure.controlStructureType("IF")
println(node2.size)
// the result is 1,and it is right!
If I want to achieve the correct results through scala1, how can I pass parameters? Or is there any other way?
I'd like to generate logging messages from within a C function embedded in a DML method. Take the example code below where the fib() function is called from the write() method of the regs bank. The log methods available to C all require a pointer to the current device.
Is there a way to get the device that calls the embedded function? Do I need to pass the device pointer into fib()?
dml 1.2;
device simple_embedded;
parameter documentation = "Embedding C code example for"
+ " Model Builder User's Guide";
parameter desc = "example of C code";
extern int fib(int x);
bank regs {
register r0 size 4 #0x0000 {
parameter allocate = false;
parameter configuration = "none";
method write(val) {
log "info": "Fibonacci(%d) = %d.", val, fib(val);
}
method read() -> (value) {
// Must be implemented to compile
}
}
}
header %{
int fib(int x);
%}
footer %{
int fib(int x) {
SIM_LOG_INFO(1, mydev, 0, "Generating Fibonacci for %d", x);
if (x < 2) return 1;
else return fib(x-1) + fib(x-2);
}
%}
I want to log from an embedded C function.
I solved this by passing the Simics conf_object_t pointer along to C. Just like implied in the question.
So you would use:
int fib(conf_object_t *mydev, int x) {
SIM_LOG_INFO(1, mydev, 0, "Generating Fibonacci for %d", x);
}
And
method write(val) {
log "info": "Fibonacci(%d) = %d.", val, fib(dev.obj,val);
}
Jakob's answer is the right one if your purpose is to offload some computations to C code (which makes sense in many situations, like when functionality is implemented by a lib).
However, if you just want a way to pass a callback to an API that asks for a function pointer, then it is easier to keep the implementation within DML and use a method reference, like:
method init() {
SIM_add_notifier(obj, trigger_fib_notifier_type, obj, &trigger_fib,
&dev.regs.r0.val);
}
method trigger_fib(conf_object_t *_, lang_void *aux) {
value = *cast(aux, uint64 *);
local int result = fib(value);
log info: "result: %d", result;
}
method fib(int x) -> (int) {
log info: "Generating Fibonacci for %d", x;
if (x < 2) return 1;
else return fib(x-1) + fib(x-2);
}
In a StringTemplate how to temporarily suppress automatic indentation?
Suppose a template:
fooTemplate() ::= <<
I want this to be indented normally.
# I do not want this line to be indented.
>>
So you can understand the motivation.
I am generating C-lang code and I do not want the preprocessor instructions to be indented. e.g.
#if
To be clear the fooTemplate is not the only template.
It is called by other templates (which may nest several levels deep).
Introducing a special character into the template to temporarily disable indentation would be acceptable.
fooTemplate() ::= <<
I want this to be indented normally.
<\u0008># I do not want this line to be indented.
>>
I see that indentation is actually applied by the 'AutoIndentWriter' https://github.com/antlr/stringtemplate4/blob/master/doc/indent.md
I implemented my own 'SemiAutoIndentWriter' which looks for a magic character (\b in my case) in the stream.
When seen the magic character sets a 'suppressIndent' switch which causes indentation to be suppressed.
package org.stringtemplate.v4;
import java.io.IOException;
import java.io.Writer;
/** Just pass through the text. */
public class SemiAutoIndentWriter extends AutoIndentWriter {
public boolean suppressIndent = false;
public SemiAutoIndentWriter (Writer out) {
super(out);
}
#Override
public int write(String str) throws IOException {
int n = 0;
int nll = newline.length();
int sl = str.length();
for (int i=0; i<sl; i++) {
char c = str.charAt(i);
if ( c=='\b' ) {
suppressIndent = true;
continue;
}
// found \n or \r\n newline?
if ( c=='\r' ) continue;
if ( c=='\n' ) {
suppressIndent = false
atStartOfLine = true;
charPosition = -nll; // set so the write below sets to 0
out.write(newline);
n += nll;
charIndex += nll;
charPosition += n; // wrote n more char
continue;
}
// normal character
// check to see if we are at the start of a line; need indent if so
if ( atStartOfLine ) {
if (! suppressIndent) n+=indent();
atStartOfLine = false;
}
n++;
out.write(c);
charPosition++;
charIndex++;
}
return n;
}
Note that the '<\b>' is not a recognized special character by ST4 but '' is recognized.
I am trying to instrument all the if statements in a C program. For example
if(condition)
statement1;
else
statement2;
is instrumented to
if(condition)
{
statement1;
}
else
{
statement2;
}
I have the following code for instrumentation
void MyRecursiveASTVisitor::InstrumentStmt(Stmt *s)
{
// Only perform if statement is not compound
SourceLocation ST = s->getLocStart();
if (!isa<CompoundStmt>(s)) {
//insert an opening brace if not present
Rewrite.InsertText(ST, "{\n", true, true);
ST = s->getLocEnd();
ST = ST.getLocWithOffset(1);
Rewrite.InsertText(ST, "\n}\n", true, true);
}
return true;
}
This works fine for almost all of the cases. However, in the case when the statement is a MACRO expansion
else
WARN((stderr,"%s: %s is a directory -- ignored\n", progname, ifname));
I get an assertion failure
Assertion `0 && "Invalid SLocOffset or bad function choice"' failed.
Can anyone explain why is this happening? Is there some special case for handling macros in clang?