1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2009-2016. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 #include <erl_nif.h>
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <limits.h>
27 
28 /* NIF interface declarations */
29 static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
30 static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
31 static void unload(ErlNifEnv* env, void* priv_data);
32 
33 /* The NIFs: */
34 static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
35 static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
36 
37 static ErlNifFunc nif_funcs[] = {
38     {"enabled", 3, enabled},
39     {"trace", 5, trace}
40 };
41 
ERL_NIF_INIT(tracer_test,nif_funcs,load,NULL,upgrade,unload)42 ERL_NIF_INIT(tracer_test, nif_funcs, load, NULL, upgrade, unload)
43 
44 static ERL_NIF_TERM atom_discard;
45 static ERL_NIF_TERM atom_ok;
46 
47 #define ASSERT(expr) assert(expr)
48 
49 static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
50 {
51 
52     atom_discard = enif_make_atom(env, "discard");
53     atom_ok = enif_make_atom(env, "ok");
54 
55     *priv_data = NULL;
56 
57     return 0;
58 }
59 
unload(ErlNifEnv * env,void * priv_data)60 static void unload(ErlNifEnv* env, void* priv_data)
61 {
62 
63 }
64 
upgrade(ErlNifEnv * env,void ** priv_data,void ** old_priv_data,ERL_NIF_TERM load_info)65 static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
66 		   ERL_NIF_TERM load_info)
67 {
68     if (*old_priv_data != NULL) {
69 	return -1; /* Don't know how to do that */
70     }
71     if (*priv_data != NULL) {
72 	return -1; /* Don't know how to do that */
73     }
74     if (load(env, priv_data, load_info)) {
75 	return -1;
76     }
77     return 0;
78 }
79 
enabled(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])80 static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
81 {
82     int state_arity;
83     const ERL_NIF_TERM *state_tuple;
84     ERL_NIF_TERM value;
85     ASSERT(argc == 3);
86 
87     if (!enif_get_tuple(env, argv[1], &state_arity, &state_tuple))
88         return atom_discard;
89 
90     if (enif_get_map_value(env, state_tuple[0], argv[0], &value)) {
91         return value;
92     } else {
93         return atom_discard;
94     }
95 }
96 
trace(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])97 static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
98 {
99     int state_arity;
100     ErlNifPid self, to;
101     ERL_NIF_TERM *tuple, msg;
102     const ERL_NIF_TERM *state_tuple;
103     ASSERT(argc == 5);
104 
105     enif_get_tuple(env, argv[1], &state_arity, &state_tuple);
106 
107     tuple = enif_alloc(sizeof(ERL_NIF_TERM)*(argc));
108     memcpy(tuple,argv,sizeof(ERL_NIF_TERM)*argc);
109 
110     msg = enif_make_tuple_from_array(env, tuple, argc);
111     enif_get_local_pid(env, state_tuple[1], &to);
112     enif_send(env, &to, NULL, msg);
113     enif_free(tuple);
114 
115     return atom_ok;
116 }
117