Previous 199869 Revisions Next

r30911 Monday 9th June, 2014 at 14:13:19 UTC by Miodrag Milanović
made LUA script execute in main thread, but console running in another (nw)
Need to generalize mechanism of communication between threads and do more cleanup
[src/emu]luaengine.c luaengine.h mame.c video.c

trunk/src/emu/luaengine.c
r30910r30911
9595   return status;
9696}
9797
98const char *lua_engine::get_prompt(int firstline) {
99   const char *p;
100   lua_getglobal(m_lua_state, firstline ? "_PROMPT" : "_PROMPT2");
101   p = lua_tostring(m_lua_state, -1);
102   if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
103   return p;
104}
105
10698/* mark in error messages for incomplete statements */
10799#define EOFMARK     "<eof>"
108100#define marklen     (sizeof(EOFMARK)/sizeof(char) - 1)
r30910r30911
122114   return 0;  /* else... */
123115}
124116
125int lua_engine::pushline(int firstline)
126{
127   char buffer[LUA_MAXINPUT];
128   char *b = buffer;
129   size_t l;
130   const char *prmt = get_prompt(firstline);
131   int readstatus = lua_readline(b, prmt);
132   lua_pop(m_lua_state, 1);  /* remove result from 'get_prompt' */
133   if (readstatus == 0)
134      return 0;  /* no input */
135   l = strlen(b);
136   if (l > 0 && b[l - 1] == '\n')  /* line ends with newline? */
137      b[l - 1] = '\0';  /* remove it */
138   if (firstline && b[0] == '=')  /* first line starts with `=' ? */
139      lua_pushfstring(m_lua_state, "return %s", b + 1);  /* change it to `return' */
140   else
141      lua_pushstring(m_lua_state, b);
142   return 1;
143}
144
145
146int lua_engine::loadline()
147{
148   int status;
149   lua_settop(m_lua_state, 0);
150   if (!pushline(1))
151      return -1;  /* no input */
152   for (;;) {  /* repeat until gets a complete line */
153      size_t l;
154      const char *line = lua_tolstring(m_lua_state, 1, &l);
155      status = luaL_loadbuffer(m_lua_state, line, l, "=stdin");
156      if (!incomplete(status)) break;  /* cannot try to add lines? */
157      if (!pushline(0))  /* no more input? */
158         return -1;
159      lua_pushliteral(m_lua_state, "\n");  /* add a new line... */
160      lua_insert(m_lua_state, -2);  /* ...between the two lines */
161      lua_concat(m_lua_state, 3);  /* join them */
162   }
163   lua_remove(m_lua_state, 1);  /* remove line */
164   return status;
165}
166
167
168117int emu_gamename(lua_State *L)
169118{
170119   lua_pushstring(L, machine_manager::instance()->machine()->system().description);
r30910r30911
199148   return 1;
200149}
201150
151
152struct msg {
153   astring text;
154   int ready;
155   astring response;
156   int status;
157   int done;
158} msg;
159
160osd_lock *lock;
161
202162void lua_engine::serve_lua()
203163{
164   osd_sleep(osd_ticks_per_second() / 1000 * 50);
204165   printf("%s v%s - %s\n%s\n%s\n\n", emulator_info::get_applongname(),build_version,emulator_info::get_fulllongname(),emulator_info::get_copyright_info(),LUA_COPYRIGHT);
205   int status;
206   while ((status = loadline()) != -1) {
207      if (status == LUA_OK) status = docall(0, LUA_MULTRET);
208      report(status);
209      if (status == LUA_OK && lua_gettop(m_lua_state) > 0) {  /* any result to print? */
210         luaL_checkstack(m_lua_state, LUA_MINSTACK, "too many results to print");
211         lua_getglobal(m_lua_state, "print");
212         lua_insert(m_lua_state, 1);
213         if (lua_pcall(m_lua_state, lua_gettop(m_lua_state) - 1, 0, 0) != LUA_OK)
214            luai_writestringerror("%s\n", lua_pushfstring(m_lua_state,
215            "error calling " LUA_QL("print") " (%s)",
216            lua_tostring(m_lua_state, -1)));
166   fflush(stdout);
167   char buff[LUA_MAXINPUT];
168   astring oldbuff;
169   
170   const char *b = LUA_PROMPT;
171   
172   do {
173      // Wait for input
174      fputs(b, stdout); fflush(stdout);  /* show prompt */       
175      fgets(buff, LUA_MAXINPUT, stdin);
176     
177      // Create message
178      osd_lock_acquire(lock);
179      if (msg.ready == 0) {
180         msg.text = oldbuff;
181         if (oldbuff.len()!=0) msg.text.cat("\n");
182         msg.text.cat(buff);
183         msg.ready = 1;
184         msg.done = 0;
217185      }
218   }
186      osd_lock_release(lock);
187     
188      // Wait for response
189      int done = 0;
190      do {
191         osd_sleep(osd_ticks_per_second() / 1000);
192         osd_lock_acquire(lock);
193         done = msg.done;
194         osd_lock_release(lock);
195      } while (done==0);
196
197      // Do action on client side
198      osd_lock_acquire(lock);
199      if (msg.status == -1){
200         b = LUA_PROMPT2;
201         oldbuff = msg.response;
202      }
203      else {
204         b = LUA_PROMPT;
205         oldbuff = "";
206      }
207      msg.done = 0;
208      osd_lock_release(lock);
209     
210   } while (1);
219211}
220212
221213static void *serve_lua(void *param)
r30910r30911
241233   luaL_requiref(m_lua_state, "emu", luaopen_emu, 1);
242234     
243235   lua_gc(m_lua_state, LUA_GCRESTART, 0);     
236   msg.ready = 0;
237   msg.status = 0;
238   msg.done = 0;
239   lock = osd_lock_alloc();
244240}
245241
246242//-------------------------------------------------
r30910r30911
261257   mg_start_thread(::serve_lua, this);
262258}
263259
260void lua_engine::periodic_check()
261{
262  osd_lock_acquire(lock);
263  if (msg.ready == 1) {
264   lua_settop(m_lua_state, 0);
265   int status = luaL_loadbuffer(m_lua_state, msg.text.cstr(), strlen(msg.text.cstr()), "=stdin");
266   if (incomplete(status)==0)  /* cannot try to add lines? */
267   {
268      if (status == LUA_OK) status = docall(0, LUA_MULTRET);
269      report(status);
270      if (status == LUA_OK && lua_gettop(m_lua_state) > 0)   /* any result to print? */
271      {
272         luaL_checkstack(m_lua_state, LUA_MINSTACK, "too many results to print");
273         lua_getglobal(m_lua_state, "print");
274         lua_insert(m_lua_state, 1);
275         if (lua_pcall(m_lua_state, lua_gettop(m_lua_state) - 1, 0, 0) != LUA_OK)
276            luai_writestringerror("%s\n", lua_pushfstring(m_lua_state,
277            "error calling " LUA_QL("print") " (%s)",
278            lua_tostring(m_lua_state, -1)));
279     }   
280   }
281   else
282   {
283     status = -1;
284   }
285   msg.status = status;
286   msg.response = msg.text;
287   msg.text = "";
288   msg.ready = 0;
289   msg.done = 1;
290  }
291  osd_lock_release(lock);
292}
293
264294//-------------------------------------------------
265295//  close - close and cleanup of lua engine
266296//-------------------------------------------------
trunk/src/emu/luaengine.h
r30910r30911
3232   void close();
3333
3434   void serve_lua();
35   void periodic_check();
3536private:   
3637   int report(int status);
3738   int docall(int narg, int nres);
38   const char *get_prompt(int firstline);
3939   int incomplete(int status) ;
40   int pushline(int firstline);
41   int loadline();
4240private:
4341   // internal state
4442   lua_State*          m_lua_state;
trunk/src/emu/mame.c
r30910r30911
250250
251251void CLIB_DECL popmessage(const char *format, ...)
252252{
253   if (machine_manager::instance()==NULL || machine_manager::instance()->machine() == NULL) return;
254
253255   // if the format is NULL, it is a signal to clear the popmessage
254256   if (format == NULL)
255257      machine_manager::instance()->machine()->ui().popup_time(0, " ");
trunk/src/emu/video.c
r30910r30911
223223   machine().osd().update(!debug && skipped_it);
224224   g_profiler.stop();
225225
226   machine().manager().lua()->periodic_check();
227
226228   // perform tasks for this frame
227229   if (!debug)
228230      machine().call_notifiers(MACHINE_NOTIFY_FRAME);

Previous 199869 Revisions Next


© 1997-2024 The MAME Team