aboutsummaryrefslogtreecommitdiff
path: root/lib/lua/src/print.c
blob: e240cfc3c6087105bb8a04d861e590a52f2b2911 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/

#include <ctype.h>
#include <stdio.h>

#define luac_c
#define LUA_CORE

#include "ldebug.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lundump.h"

#define PrintFunction	luaU_print

#define Sizeof(x)	((int)sizeof(x))
#define VOID(p)		((const void*)(p))

static void PrintString(const TString* ts)
{
 const char* s=getstr(ts);
 size_t i,n=ts->tsv.len;
 putchar('"');
 for (i=0; i<n; i++)
 {
  int c=s[i];
  switch (c)
  {
   case '"': printf("\\\""); break;
   case '\\': printf("\\\\"); break;
   case '\a': printf("\\a"); break;
   case '\b': printf("\\b"); break;
   case '\f': printf("\\f"); break;
   case '\n': printf("\\n"); break;
   case '\r': printf("\\r"); break;
   case '\t': printf("\\t"); break;
   case '\v': printf("\\v"); break;
   default:	if (isprint((unsigned char)c))
   			putchar(c);
		else
			printf("\\%03u",(unsigned char)c);
  }
 }
 putchar('"');
}

static void PrintConstant(const Proto* f, int i)
{
 const TValue* o=&f->k[i];
 switch (ttype(o))
 {
  case LUA_TNIL:
	printf("nil");
	break;
  case LUA_TBOOLEAN:
	printf(bvalue(o) ? "true" : "false");
	break;
  case LUA_TNUMBER:
	printf(LUA_NUMBER_FMT,nvalue(o));
	break;
  case LUA_TSTRING:
	PrintString(rawtsvalue(o));
	break;
  default:				/* cannot happen */
	printf("? type=%d",ttype(o));
	break;
 }
}

static void PrintCode(const Proto* f)
{
 const Instruction* code=f->code;
 int pc,n=f->sizecode;
 for (pc=0; pc<n; pc++)
 {
  Instruction i=code[pc];
  OpCode o=GET_OPCODE(i);
  int a=GETARG_A(i);
  int b=GETARG_B(i);
  int c=GETARG_C(i);
  int bx=GETARG_Bx(i);
  int sbx=GETARG_sBx(i);
  int line=getline(f,pc);
  printf("\t%d\t",pc+1);
  if (line>0) printf("[%d]\t",line); else printf("[-]\t");
  printf("%-9s\t",luaP_opnames[o]);
  switch (getOpMode(o))
  {
   case iABC:
    printf("%d",a);
    if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b);
    if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c);
    break;
   case iABx:
    if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx);
    break;
   case iAsBx:
    if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx);
    break;
  }
  switch (o)
  {
   case OP_LOADK:
    printf("\t; "); PrintConstant(f,bx);
    break;
   case OP_GETUPVAL:
   case OP_SETUPVAL:
    printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-");
    break;
   case OP_GETGLOBAL:
   case OP_SETGLOBAL:
    printf("\t; %s",svalue(&f->k[bx]));
    break;
   case OP_GETTABLE:
   case OP_SELF:
    if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
    break;
   case OP_SETTABLE:
   case OP_ADD:
   case OP_SUB:
   case OP_MUL:
   case OP_DIV:
   case OP_POW:
   case OP_EQ:
   case OP_LT:
   case OP_LE:
    if (ISK(b) || ISK(c))
    {
     printf("\t; ");
     if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
     printf(" ");
     if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
    }
    break;
   case OP_JMP:
   case OP_FORLOOP:
   case OP_FORPREP:
    printf("\t; to %d",sbx+pc+2);
    break;
   case OP_CLOSURE:
    printf("\t; %p",VOID(f->p[bx]));
    break;
   case OP_SETLIST:
    if (c==0) printf("\t; %d",(int)code[++pc]);
    else printf("\t; %d",c);
    break;
   default:
    break;
  }
  printf("\n");
 }
}

#define SS(x)	(x==1)?"":"s"
#define S(x)	x,SS(x)

static void PrintHeader(const Proto* f)
{
 const char* s=getstr(f->source);
 if (*s=='@' || *s=='=')
  s++;
 else if (*s==LUA_SIGNATURE[0])
  s="(bstring)";
 else
  s="(string)";
 printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n",
 	(f->linedefined==0)?"main":"function",s,
	f->linedefined,f->lastlinedefined,
	S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f));
 printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
	f->numparams,f->is_vararg?"+":"",SS(f->numparams),
	S(f->maxstacksize),S(f->nups));
 printf("%d local%s, %d constant%s, %d function%s\n",
	S(f->sizelocvars),S(f->sizek),S(f->sizep));
}

static void PrintConstants(const Proto* f)
{
 int i,n=f->sizek;
 printf("constants (%d) for %p:\n",n,VOID(f));
 for (i=0; i<n; i++)
 {
  printf("\t%d\t",i+1);
  PrintConstant(f,i);
  printf("\n");
 }
}

static void PrintLocals(const Proto* f)
{
 int i,n=f->sizelocvars;
 printf("locals (%d) for %p:\n",n,VOID(f));
 for (i=0; i<n; i++)
 {
  printf("\t%d\t%s\t%d\t%d\n",
  i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
 }
}

static void PrintUpvalues(const Proto* f)
{
 int i,n=f->sizeupvalues;
 printf("upvalues (%d) for %p:\n",n,VOID(f));
 if (f->upvalues==NULL) return;
 for (i=0; i<n; i++)
 {
  printf("\t%d\t%s\n",i,getstr(f->upvalues[i]));
 }
}

void PrintFunction(const Proto* f, int full)
{
 int i,n=f->sizep;
 PrintHeader(f);
 PrintCode(f);
 if (full)
 {
  PrintConstants(f);
  PrintLocals(f);
  PrintUpvalues(f);
 }
 for (i=0; i<n; i++) PrintFunction(f->p[i],full);
}
ect(a_rect), parent_button(a_parent_button) { } std::wstring text; core::rect<s32> rect; gui::IGUIButton *parent_button; }; public: GUIFormSpecMenu(JoystickController *joystick, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, Client *client, ISimpleTextureSource *tsrc, IFormSource* fs_src, TextDest* txt_dst, bool remap_dbl_click = true); ~GUIFormSpecMenu(); static void create(GUIFormSpecMenu *&cur_formspec, Client *client, JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest); void setFormSpec(const std::string &formspec_string, const InventoryLocation &current_inventory_location) { m_formspec_string = formspec_string; m_current_inventory_location = current_inventory_location; regenerateGui(m_screensize_old); } // form_src is deleted by this GUIFormSpecMenu void setFormSource(IFormSource *form_src) { delete m_form_src; m_form_src = form_src; } // text_dst is deleted by this GUIFormSpecMenu void setTextDest(TextDest *text_dst) { delete m_text_dst; m_text_dst = text_dst; } void allowClose(bool value) { m_allowclose = value; } void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0)) { m_lock = lock; m_lockscreensize = basescreensize; } void removeChildren(); void setInitialFocus(); void setFocus(const std::string &elementname) { m_focused_element = elementname; } /* Remove and re-add (or reposition) stuff */ void regenerateGui(v2u32 screensize); ItemSpec getItemAtPos(v2s32 p) const; void drawList(const ListDrawSpec &s, int phase, bool &item_hovered); void drawSelectedItem(); void drawMenu(); void updateSelectedItem(); ItemStack verifySelectedItem(); void acceptInput(FormspecQuitMode quitmode); bool preprocessEvent(const SEvent& event); bool OnEvent(const SEvent& event); bool doPause; bool pausesGame() { return doPause; } GUITable* getTable(const std::string &tablename); std::vector<std::string>* getDropDownValues(const std::string &name); #ifdef __ANDROID__ bool getAndroidUIInput(); #endif protected: v2s32 getBasePos() const { return padding + offset + AbsoluteRect.UpperLeftCorner; } v2s32 padding; v2s32 spacing; v2s32 imgsize; v2s32 offset; v2s32 pos_offset; std::stack<v2s32> container_stack; InventoryManager *m_invmgr; ISimpleTextureSource *m_tsrc; Client *m_client; std::string m_formspec_string; InventoryLocation m_current_inventory_location; std::vector<ListDrawSpec> m_inventorylists; std::vector<ListRingSpec> m_inventory_rings; std::vector<ImageDrawSpec> m_backgrounds; std::vector<ImageDrawSpec> m_images; std::vector<ImageDrawSpec> m_itemimages; std::vector<BoxDrawSpec> m_boxes; std::unordered_map<std::string, bool> field_close_on_enter; std::vector<FieldSpec> m_fields; std::vector<StaticTextSpec> m_static_texts; std::vector<std::pair<FieldSpec,GUITable*> > m_tables; std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes; std::map<std::string, TooltipSpec> m_tooltips; std::vector<std::pair<FieldSpec,gui::IGUIScrollBar*> > m_scrollbars; std::vector<std::pair<FieldSpec, std::vector<std::string> > > m_dropdowns; ItemSpec *m_selected_item = nullptr; u32 m_selected_amount = 0; bool m_selected_dragging = false; // WARNING: BLACK MAGIC // Used to guess and keep up with some special things the server can do. // If name is "", no guess exists. ItemStack m_selected_content_guess; InventoryLocation m_selected_content_guess_inventory; v2s32 m_pointer; v2s32 m_old_pointer; // Mouse position after previous mouse event gui::IGUIStaticText *m_tooltip_element = nullptr; u64 m_tooltip_show_delay; bool m_tooltip_append_itemname; u64 m_hovered_time = 0; s32 m_old_tooltip_id = -1; bool m_auto_place = false; bool m_allowclose = true; bool m_lock = false; v2u32 m_lockscreensize; bool m_bgfullscreen; bool m_slotborder; video::SColor m_bgcolor; video::SColor m_fullscreen_bgcolor; video::SColor m_slotbg_n; video::SColor m_slotbg_h; video::SColor m_slotbordercolor; video::SColor m_default_tooltip_bgcolor; video::SColor m_default_tooltip_color; private: IFormSource *m_form_src; TextDest *m_text_dst; u32 m_formspec_version = 0; std::string m_focused_element = ""; JoystickController *m_joystick; typedef struct { bool explicit_size; v2f invsize; v2s32 size; v2f32 offset; v2f32 anchor; core::rect<s32> rect; v2s32 basepos; v2u32 screensize; std::string focused_fieldname; GUITable::TableOptions table_options; GUITable::TableColumns table_columns; // used to restore table selection/scroll/treeview state std::unordered_map<std::string, GUITable::DynamicData> table_dyndata; } parserData; typedef struct { bool key_up; bool key_down; bool key_enter; bool key_escape; } fs_key_pendig; fs_key_pendig current_keys_pending; std::string current_field_enter_pending = ""; void parseElement(parserData* data, const std::string &element); void parseSize(parserData* data, const std::string &element); void parseContainer(parserData* data, const std::string &element); void parseContainerEnd(parserData* data); void parseList(parserData* data, const std::string &element); void parseListRing(parserData* data, const std::string &element); void parseCheckbox(parserData* data, const std::string &element); void parseImage(parserData* data, const std::string &element); void parseItemImage(parserData* data, const std::string &element); void parseButton(parserData* data, const std::string &element, const std::string &typ); void parseBackground(parserData* data, const std::string &element); void parseTableOptions(parserData* data, const std::string &element); void parseTableColumns(parserData* data, const std::string &element); void parseTable(parserData* data, const std::string &element); void parseTextList(parserData* data, const std::string &element); void parseDropDown(parserData* data, const std::string &element); void parseFieldCloseOnEnter(parserData *data, const std::string &element); void parsePwdField(parserData* data, const std::string &element); void parseField(parserData* data, const std::string &element, const std::string &type); void parseSimpleField(parserData* data,std::vector<std::string> &parts); void parseTextArea(parserData* data,std::vector<std::string>& parts, const std::string &type); void parseLabel(parserData* data, const std::string &element); void parseVertLabel(parserData* data, const std::string &element); void parseImageButton(parserData* data, const std::string &element, const std::string &type); void parseItemImageButton(parserData* data, const std::string &element); void parseTabHeader(parserData* data, const std::string &element); void parseBox(parserData* data, const std::string &element); void parseBackgroundColor(parserData* data, const std::string &element); void parseListColors(parserData* data, const std::string &element); void parseTooltip(parserData* data, const std::string &element); bool parseVersionDirect(const std::string &data); bool parseSizeDirect(parserData* data, const std::string &element); void parseScrollBar(parserData* data, const std::string &element); bool parsePositionDirect(parserData *data, const std::string &element); void parsePosition(parserData *data, const std::string &element); bool parseAnchorDirect(parserData *data, const std::string &element); void parseAnchor(parserData *data, const std::string &element); void tryClose(); void showTooltip(const std::wstring &text, const irr::video::SColor &color, const irr::video::SColor &bgcolor); /** * check if event is part of a double click * @param event event to evaluate * @return true/false if a doubleclick was detected */ bool DoubleClickDetection(const SEvent event); struct clickpos { v2s32 pos; s64 time; }; clickpos m_doubleclickdetect[2]; int m_btn_height; gui::IGUIFont *m_font = nullptr; std::wstring getLabelByID(s32 id); std::string getNameByID(s32 id); #ifdef __ANDROID__ v2s32 m_down_pos; std::string m_JavaDialogFieldName; #endif /* If true, remap a double-click (or double-tap) action to ESC. This is so * that, for example, Android users can double-tap to close a formspec. * * This value can (currently) only be set by the class constructor * and the default value for the setting is true. */ bool m_remap_dbl_click; }; class FormspecFormSource: public IFormSource { public: FormspecFormSource(const std::string &formspec): m_formspec(formspec) { } ~FormspecFormSource() = default; void setForm(const std::string &formspec) { m_formspec = FORMSPEC_VERSION_STRING + formspec; } const std::string &getForm() const { return m_formspec; } std::string m_formspec; };