Project

General

Profile

« Previous | Next » 

Revision 2836

Added by stephane about 13 years ago

Utils_g

View differences:

src/scol_gbase.c
23 23
http://www.gnu.org/copyleft/lesser.txt
24 24

  
25 25
For others informations, please contact us from http://www.scolring.org/
26
*/

27

  
26
*/
27

  
28 28
#include "../include/scol_gbase.h"
29 29

  
30
#ifdef __cplusplus

31
#error This source file is not C++ but rather C. Please use a C-compiler

32
#endif

33

  
34
#if ((defined _WIN32) || (defined __WIN32__))

35
cbmachine ww;

36
#endif

37
mmachine  mm;

38

  
39

  
40
/**

41
 * \brief _gbaseUserName : Returns the user (or real) name

42
 *

43
 * fun [] S

44
 *

45
 * \param : nothing

46
 * \return S : this name

47
 */

48
int SCOL_gbaseUserName (mmachine m)

49
{

50
    const gchar * name;

51

  
52
    name = g_get_user_name ();

53
    if (name == NULL)

54
        name = g_get_real_name ();

55

  
56
    if (name == NULL)

57
    {

58
        Mpushstrbloc (m, "unknown");

59
        return 0;

60
    }

61
    Mpushstrbloc (m, (char *) name);

62
    return 0;

63
}

64

  
65
/**

66
 * \brief _gBaseHostName : Returns the host name

67
 *

68
 * fun [] S

69
 *

70
 * \param : nothing

71
 * \return S : this name

72
 */

73
int SCOL_gBaseHostName (mmachine m)

74
{

75
    const gchar * name;

76

  
77
    name = g_get_host_name ();

78
    if (name == NULL)

79
    {

80
        Mpushstrbloc (m, "unknown");

81
        return 0;

82
    }

83
    Mpushstrbloc (m, (char *) name);

84
    return 0;

85
}

86

  
87
/**

88
 * \brief _gBaseDirCur : Returns the current directory (by default on MS Windows "C:\Program Files\Scol Voyager")

89
 *

90
 * fun [] S

91
 *

92
 * \param : nothing

93
 * \return S : this directory or "unknown" if undefined

94
 */

95
int SCOL_gBaseDirCur (mmachine m)

96
{

97
    const gchar * name;

98

  
99
    name = g_get_current_dir ();

100
    if (name == NULL)

101
    {

102
        Mpushstrbloc (m, "unknown");

103
        return 0;

104
    }

105
    Mpushstrbloc (m, (char *) name);

106
    return 0;

107
}

108

  
109
/**

110
 * \brief _gBasePathAbsolute : Returns 1 if the given file_name is an absolute file name.

111
 *

112
 * fun [S] I

113
 *

114
 * \param S : any path

115
 * \return I : 1 if TRUE,otherwise 0

116
 */

117
 int SCOL_gBasePathAbsolute (mmachine m)

118
 {

119
    int mpath;

120
    gboolean value;

121

  
122
    mpath = MMpull (m);

123
    if (mpath == NIL)

124
    {

125
        MMpush (m, NIL);

126
        return 0;

127
    }

128

  
129
    value = g_path_is_absolute (MMstartstr (m, MTOP (mpath)));

130
    MMpush (m, ITOM (value));

131
    return 0;

132
 }

133

  
134
/**

135
 * \brief _gBasePathBase : Returns the last component of the filename

136
 *

137
 * fun [S] S

138
 *

139
 * \param S : any path

140
 * \return S : this last component

141
 */

142
int SCOL_gBasePathBase (mmachine m)

143
{

144
    int mpath;

145
    gchar *base;

146

  
147
    mpath = MMpull (m);

148
    if (mpath == NIL)

149
    {

150
        MMpush (m, NIL);

151
        return 0;

152
    }

153
    base = g_path_get_basename (MMstartstr (m, MTOP (mpath)));

154
    Mpushstrbloc (m, base);

155
    g_free (base);

156
    return 0;

157
}

158

  
159
/**

160
 * \brief _gBasePathDir : Returns the directory components of a file name.

161
 *

162
 * fun [S] S

163
 *

164
 * \param S : any path

165
 * \return S : this directory

166
 */

167
int SCOL_gBasePathDir (mmachine m)

168
{

169
    int mpath;

170
    gchar *dir;

171

  
172
    mpath = MMpull (m);

173
    if (mpath == NIL)

174
    {

175
        MMpush (m, NIL);

176
        return 0;

177
    }

178
    dir = g_path_get_dirname (MMstartstr (m, MTOP (mpath)));

179
    Mpushstrbloc (m, dir);

180
    g_free (dir);

181
    return 0;

182
}

183

  
184
/**

185
 * \brief _gBasePathBuild : Creates a filename from a list of elements using the correct separator for filenames.

186
 *

187
 * fun [[S r1] I] S

188
 *

189
 * \param [S r1] : a list of elements (typically, a list of directory : a :: b :: c :: file.ext)

190
 * \param I : 1 : OS separator (e.g. "\" on MS Windows, "/" on Linux), otherwise Scol separator ("/")

191
 * \return S : the filename

192
 */

193
int SCOL_gBasePathBuild (mmachine m)

194
{

195
    int mlist, mflag;

196
    int size = 0, i = 0;

197
    gchar **list;

198
    gchar *fn;

199

  
200
    mflag = MTOI (MMpull (m));

201
    mlist = MMget (m, 0);

202
    if (mlist == NIL)

203
    {

204
        MMpush (m, NIL);

205
        return 0;

206
    }

207
    mlist = MTOP (mlist);

208

  
209
    while (mlist != NIL)

210
    {

211
        size++;

212
        mlist = MMfetch (m, mlist, 1)>>1;

213
    }

214

  
215
    list = g_new0 (gchar*, size + 2);

216
    mlist = MTOP (MMpull (m));

217
    for (; i < size; i++)

218
    {

219
        list[i] = MMstartstr (m, MTOP (MMfetch (m, mlist, 0)));

220
        mlist = MTOP (MMfetch (m, mlist, 1));

221
    }

222

  
223
    if (mflag == 1)

224
        fn = g_build_filenamev (list);

225
    else

226
        fn = g_build_pathv ("/", list);

227
    Mpushstrbloc (m, fn);

228
    g_free (list);

229
    g_free (fn);

230
    return 0;

231
}

232

  
233
/**

234
 * \brief _gBaseStringUTF8 : Converts a string in the current locale into a UTF-8 string or reverse.

235
 *

236
 * fun [S I] S

237
 *

238
 * \param S : any string

239
 * \param I : 1 from locale to UTF8, 0 from UTF-8 to current locale

240
 * \return : the new string

241
 */

242
int SCOL_gBaseStringUTF8 (mmachine m)

243
{

244
    int mstring, mflag;

245
    gchar *string;

246

  
247
    mflag = MMpull (m);

248
    mstring = MMpull (m);

249

  
250
    if (mstring == NIL)

251
    {

252
        MMpush (m, NIL);

253
        return 0;

254
    }

255
    if (mflag)

256
        string = SCOLUTF8 (MMstartstr (m, MTOP (mstring)), -1);

257
    else

258
        string = UTF8SCOL (MMstartstr (m, MTOP (mstring)), -1);

259
    Mpushstrbloc (m, string);

260
    g_free (string);

261
    return 0;

262
}

263

  
264
/**

265
 * \brief _gbaseChecksumS : Computes the checksum of a string.

266
 *

267
 * fun [S I] S

268
 *

269
 * \param S : any string

270
 * \param I : the hashing algorithm to use : 0 -> MD5 (default), 1 -> SHA-1, 2 -> SHA-256

271
 * \return S : the checksum as an hexadecimal string.

272
 */

273
int SCOL_gbaseChecksumS (mmachine m)

274
{

275
    int mstring, mtype;

276
    GChecksumType type = G_CHECKSUM_MD5;

277
    gchar *string;

278

  
279
    mtype = MTOI (MMpull (m));

280
    mstring = MMpull (m);

281

  
282
    if (mstring == NIL)

283
    {

284
        MMpush (m, NIL);

285
        return 0;

286
    }

287
    mstring = MTOP (mstring);

288

  
289
    if (mtype == 1)

290
        type = G_CHECKSUM_SHA1;

291
    else if (mtype == 2)

292
        type = G_CHECKSUM_SHA256;

293

  
294
    string = g_compute_checksum_for_string (type, MMstartstr (m, mstring), -1);

295
    Mpushstrbloc (m, string);

296
    g_free (string);

297
    return 0;

298
}

299

  
300
/**

301
 * \brief _gbaseChecksumP : Computes the checksum of a file.

302
 *

303
 * fun [P I] S

304
 *

305
 * \param S : any file (read referenced only)

306
 * \param I : the hashing algorithm to use : 0 -> MD5 (default), 1 -> SHA-1, 2 -> SHA-256

307
 * \return S : the checksum as an hexadecimal string.

308
 */

309
int SCOL_gbaseChecksumP (mmachine m)

310
{

311
    /* #define SCSP_MAX_SIZE G_MAXUINT-1 */ /* i'm stupid ! */

312
    #define SCSP_MAX_SIZE 1024*32   /* 32 ko / each loop */

313
    int mfile, mtype;

314
    guchar data[SCSP_MAX_SIZE];

315
    gsize size = 0;

316
    GChecksumType type = G_CHECKSUM_MD5;

317
    GChecksum *cs;

318
    const gchar *string;

319
    FILE *file;

320

  
321
    mtype = MTOI (MMpull (m));

322
    mfile = MMpull (m);

323

  
324
    if (mfile == NIL)

325
    {

326
        MMpush (m, NIL);

327
        return 0;

328
    }

329
    mfile = MTOP (mfile);

330

  
331
    file = fopen (MMstartstr (m, mfile), "rb");

332
    if (file == NULL)

333
    {

334
        MMpush (m, NIL);

335
        return 0;

336
    }

337

  
338
    if (mtype == 1)

339
        type = G_CHECKSUM_SHA1;

340
    else if (mtype == 2)

341
        type = G_CHECKSUM_SHA256;

342

  
343
    cs = g_checksum_new (type);

344
    do

345
    {

346
        size = fread((void *) data, sizeof (guchar), SCSP_MAX_SIZE, file);

347
        g_checksum_update (cs, data, size);

348
    }

349
    while (size == SCSP_MAX_SIZE);

350
    fclose (file);

351

  
352
    string = g_checksum_get_string (cs);

353
    Mpushstrbloc (m, (char *) string);

354
    g_checksum_free (cs);

355
    return 0;

356
}

357

  
358
/**

359
 * \brief _gbaseSleep : Pauses the current thread for the given number of milliseconds.

360
 *

361
 * fun [I] I

362
 *

363
 * \param I : the number of milliseconds

364
 * \return I : 0 if success, nil if error

365
 */

366
int SCOL_gbaseSleep (mmachine m)

367
{

368
    int msleep;

369

  
370
    msleep = MTOI (MMpull (m));

371
    if (msleep <= 0)

372
    {

373
        MMpush (m, NIL);

374
        return 0;

375
    }

376

  
377
    g_usleep (1000*msleep);

378
    MMpush (m, ITOM (0));

379
    return 0;

380
}

381

  
382
/**

383
 * \brief _gbaseFileStat : it should not be used, at this time

384
 *

385
 * fun [P] [I I I I]

386
 *

387
 * \param P : a filename (read reference only)

388
 * \return [I I I I] : size, last access, last modification, last state changed

389
 */

390
int SCOL_gbaseFileStat (mmachine m)

391
{

392
    int mfile;

30
#ifdef __cplusplus
31
#error This source file is not C++ but rather C. Please use a C-compiler
32
#endif
33

  
34
#if ((defined _WIN32) || (defined __WIN32__))
35
cbmachine ww;
36
#endif
37
mmachine  mm;
38

  
39

  
40
/**
41
 * \brief _gbaseUserName : Returns the user (or real) name
42
 *
43
 * fun [] S
44
 *
45
 * \param void : nothing
46
 * \return S : this name
47
 */
48
int SCOL_gbaseUserName (mmachine m)
49
{
50
    const gchar * name;
51

  
52
    name = g_get_user_name ();
53
    if (name == NULL)
54
        name = g_get_real_name ();
55

  
56
    if (name == NULL)
57
    {
58
        Mpushstrbloc (m, "unknown");
59
        return 0;
60
    }
61
    Mpushstrbloc (m, (char *) name);
62
    return 0;
63
}
64

  
65
/**
66
 * \brief _gBaseHostName : Returns the host name
67
 *
68
 * fun [] S
69
 *
70
 * \param void : nothing
71
 * \return S : this name
72
 */
73
int SCOL_gBaseHostName (mmachine m)
74
{
75
    const gchar * name;
76

  
77
    name = g_get_host_name ();
78
    if (name == NULL)
79
    {
80
        Mpushstrbloc (m, "unknown");
81
        return 0;
82
    }
83
    Mpushstrbloc (m, (char *) name);
84
    return 0;
85
}
86

  
87
/**
88
 * \brief _gBaseDirCur : Returns the current directory (by default on MS Windows "C:\Program Files\Scol Voyager")
89
 *
90
 * fun [] S
91
 *
92
 * \param void : nothing
93
 * \return S : this directory or "unknown" if undefined
94
 */
95
int SCOL_gBaseDirCur (mmachine m)
96
{
97
    const gchar * name;
98

  
99
    name = g_get_current_dir ();
100
    if (name == NULL)
101
    {
102
        Mpushstrbloc (m, "unknown");
103
        return 0;
104
    }
105
    Mpushstrbloc (m, (char *) name);
106
    return 0;
107
}
108

  
109
/**
110
 * \brief _gBasePathAbsolute : Returns 1 if the given file_name is an absolute file name.
111
 *
112
 * fun [S] I
113
 *
114
 * \param S : any path
115
 * \return I : 1 if TRUE,otherwise 0
116
 */
117
 int SCOL_gBasePathAbsolute (mmachine m)
118
 {
119
    int mpath;
120
    gboolean value;
121

  
122
    mpath = MMpull (m);
123
    if (mpath == NIL)
124
    {
125
        MMpush (m, NIL);
126
        return 0;
127
    }
128

  
129
    value = g_path_is_absolute (MMstartstr (m, MTOP (mpath)));
130
    MMpush (m, ITOM (value));
131
    return 0;
132
 }
133

  
134
/**
135
 * \brief _gBasePathBase : Returns the last component of the filename
136
 *
137
 * fun [S] S
138
 *
139
 * \param S : any path
140
 * \return S : this last component
141
 */
142
int SCOL_gBasePathBase (mmachine m)
143
{
144
    int mpath;
145
    gchar *base;
146

  
147
    mpath = MMpull (m);
148
    if (mpath == NIL)
149
    {
150
        MMpush (m, NIL);
151
        return 0;
152
    }
153
    base = g_path_get_basename (MMstartstr (m, MTOP (mpath)));
154
    Mpushstrbloc (m, base);
155
    g_free (base);
156
    return 0;
157
}
158

  
159
/**
160
 * \brief _gBasePathDir : Returns the directory components of a file name.
161
 *
162
 * fun [S] S
163
 *
164
 * \param S : any path
165
 * \return S : this directory
166
 */
167
int SCOL_gBasePathDir (mmachine m)
168
{
169
    int mpath;
170
    gchar *dir;
171

  
172
    mpath = MMpull (m);
173
    if (mpath == NIL)
174
    {
175
        MMpush (m, NIL);
176
        return 0;
177
    }
178
    dir = g_path_get_dirname (MMstartstr (m, MTOP (mpath)));
179
    Mpushstrbloc (m, dir);
180
    g_free (dir);
181
    return 0;
182
}
183

  
184
/**
185
 * \brief _gBasePathBuild : Creates a filename from a list of elements using the correct separator for filenames.
186
 *
187
 * fun [[S r1] I] S
188
 *
189
 * \param [S r1] : a list of elements (typically, a list of directory = a :: b :: c :: file.ext)
190
 * \param I : 1 = OS separator (e.g. "\" on MS Windows, "/" on Linux), otherwise Scol separator ("/")
191
 * \return S : the filename
192
 */
193
int SCOL_gBasePathBuild (mmachine m)
194
{
195
    int mlist, mflag;
196
    int size = 0, i = 0;
197
    gchar **list;
198
    gchar *fn;
199

  
200
    mflag = MTOI (MMpull (m));
201
    mlist = MMget (m, 0);
202
    if (mlist == NIL)
203
    {
204
        MMpush (m, NIL);
205
        return 0;
206
    }
207
    mlist = MTOP (mlist);
208

  
209
    while (mlist != NIL)
210
    {
211
        size++;
212
        mlist = MMfetch (m, mlist, 1)>>1;
213
    }
214

  
215
    list = g_new0 (gchar*, size + 2);
216
    mlist = MTOP (MMpull (m));
217
    for (; i < size; i++)
218
    {
219
        list[i] = MMstartstr (m, MTOP (MMfetch (m, mlist, 0)));
220
        mlist = MTOP (MMfetch (m, mlist, 1));
221
    }
222

  
223
    if (mflag == 1)
224
        fn = g_build_filenamev (list);
225
    else
226
        fn = g_build_pathv ("/", list);
227
    Mpushstrbloc (m, fn);
228
    g_free (list);
229
    g_free (fn);
230
    return 0;
231
}
232

  
233
/**
234
 * \brief _gBaseStringUTF8 : Converts a string in the current locale into a UTF-8 string or reverse.
235
 *
236
 * fun [S I] S
237
 *
238
 * \param S : any string
239
 * \param I : 1 from locale to UTF8, 0 from UTF-8 to current locale
240
 * \return S : the new string
241
 */
242
int SCOL_gBaseStringUTF8 (mmachine m)
243
{
244
    int mstring, mflag;
245
    gchar *string;
246

  
247
    mflag = MMpull (m);
248
    mstring = MMpull (m);
249

  
250
    if (mstring == NIL)
251
    {
252
        MMpush (m, NIL);
253
        return 0;
254
    }
255
    if (mflag)
256
        string = SCOLUTF8 (MMstartstr (m, MTOP (mstring)), -1);
257
    else
258
        string = UTF8SCOL (MMstartstr (m, MTOP (mstring)), -1);
259
    Mpushstrbloc (m, string);
260
    g_free (string);
261
    return 0;
262
}
263

  
264
/**
265
 * \brief _gbaseChecksumS : Computes the checksum of a string.
266
 *
267
 * fun [S I] S
268
 *
269
 * \param S : any string
270
 * \param I : the hashing algorithm to use = 0 -> MD5 (default), 1 -> SHA-1, 2 -> SHA-256
271
 * \return S : the checksum as an hexadecimal string.
272
 */
273
int SCOL_gbaseChecksumS (mmachine m)
274
{
275
    int mstring, mtype;
276
    GChecksumType type = G_CHECKSUM_MD5;
277
    gchar *string;
278

  
279
    mtype = MTOI (MMpull (m));
280
    mstring = MMpull (m);
281

  
282
    if (mstring == NIL)
283
    {
284
        MMpush (m, NIL);
285
        return 0;
286
    }
287
    mstring = MTOP (mstring);
288

  
289
    if (mtype == 1)
290
        type = G_CHECKSUM_SHA1;
291
    else if (mtype == 2)
292
        type = G_CHECKSUM_SHA256;
293

  
294
    string = g_compute_checksum_for_string (type, MMstartstr (m, mstring), -1);
295
    Mpushstrbloc (m, string);
296
    g_free (string);
297
    return 0;
298
}
299

  
300
/**
301
 * \brief _gbaseChecksumP : Computes the checksum of a file.
302
 *
303
 * fun [P I] S
304
 *
305
 * \param S : any file (read referenced only)
306
 * \param I : the hashing algorithm to use = 0 -> MD5 (default), 1 -> SHA-1, 2 -> SHA-256
307
 * \return S : the checksum as an hexadecimal string.
308
 */
309
int SCOL_gbaseChecksumP (mmachine m)
310
{
311
    /* #define SCSP_MAX_SIZE G_MAXUINT-1 */ /* i'm stupid ! */
312
    #define SCSP_MAX_SIZE 1024*32   /* 32 ko / each loop */
313
    int mfile, mtype;
314
    guchar data[SCSP_MAX_SIZE];
315
    gsize size = 0;
316
    GChecksumType type = G_CHECKSUM_MD5;
317
    GChecksum *cs;
318
    const gchar *string;
319
    FILE *file;
320

  
321
    mtype = MTOI (MMpull (m));
322
    mfile = MMpull (m);
323

  
324
    if (mfile == NIL)
325
    {
326
        MMpush (m, NIL);
327
        return 0;
328
    }
329
    mfile = MTOP (mfile);
330

  
331
    file = fopen (MMstartstr (m, mfile), "rb");
332
    if (file == NULL)
333
    {
334
        MMpush (m, NIL);
335
        return 0;
336
    }
337

  
338
    if (mtype == 1)
339
        type = G_CHECKSUM_SHA1;
340
    else if (mtype == 2)
341
        type = G_CHECKSUM_SHA256;
342

  
343
    cs = g_checksum_new (type);
344
    do
345
    {
346
        size = fread((void *) data, sizeof (guchar), SCSP_MAX_SIZE, file);
347
        g_checksum_update (cs, data, size);
348
    }
349
    while (size == SCSP_MAX_SIZE);
350
    fclose (file);
351

  
352
    string = g_checksum_get_string (cs);
353
    Mpushstrbloc (m, (char *) string);
354
    g_checksum_free (cs);
355
    return 0;
356
}
357

  
358
/**
359
 * \brief _gbaseSleep : Pauses the current thread for the given number of milliseconds.
360
 *
361
 * fun [I] I
362
 *
363
 * \param I : the number of milliseconds
364
 * \return I : 0 if success, nil if error
365
 */
366
int SCOL_gbaseSleep (mmachine m)
367
{
368
    int msleep;
369

  
370
    msleep = MTOI (MMpull (m));
371
    if (msleep <= 0)
372
    {
373
        MMpush (m, NIL);
374
        return 0;
375
    }
376

  
377
    g_usleep (1000*msleep);
378
    MMpush (m, ITOM (0));
379
    return 0;
380
}
381

  
382
/**
383
 * \brief _gbaseFileStat : it should not be used, at this time
384
 *
385
 * fun [P] [I I I I]
386
 *
387
 * \param P : a filename (read reference only)
388
 * \return [I I I I] : size, last access, last modification, last state changed
389
 */
390
int SCOL_gbaseFileStat (mmachine m)
391
{
392
    int mfile;
393 393
    int result;
394
    #if ((defined _WIN32) || (defined __WIN32__))

394
    #if ((defined _WIN32) || (defined __WIN32__))
395 395
    GStatBuf *s = NULL;
396 396
    #else
397 397
    struct stat *s = NULL;
398
    #endif

399

  
400
    mfile = MMpull(m);

401
    if (mfile == NIL)

402
    {

403
        MMpush (m, NIL);

404
        return 0;

405
    }

406
    mfile = MTOP (mfile);

407

  
408
    result = g_stat (MMstartstr (m, mfile), s);

409
    if (result != 0)

410
    {

411
        MMpush (m, NIL);

412
        return 0;

413
    }

414
    MMpush (m, ITOM (s->st_size));

415
    MMpush (m, ITOM (s->st_atime));

416
    MMpush (m, ITOM (s->st_mtime));

417
    MMpush (m, ITOM (s->st_ctime));

418
    MMpush (m, ITOM (4));

419
    MBdeftab (m);

420

  
421
    return 0;

422
}

423

  
424
/**

425
 * \brief _gbaseIsIp : Tests if a string is a form of an IPv4 or IPv6 address (like "123.210.012.231").

426
 * fun [S] I

427
 * \param S : any string

428
 * \return I : 1 if TRUE (the string is an IP address), 0 if FALSE

429
 */

430
int SCOL_gbaseIsIp (mmachine m)

431
{

432
    int ms;

433

  
434
    ms = MMpull (m);

435
    if (ms == NIL)

436
    {

437
        MMpush (m, NIL);

438
        return 0;

439
    }

440
    MMpush (m, ITOM (g_hostname_is_ip_address (MMstartstr (m, MTOP (ms)))));

441
    return 0;

442
}

443

  
444

  
445

  
446

  
447

  
448

  
398
    #endif
399

  
400
    mfile = MMpull(m);
401
    if (mfile == NIL)
402
    {
403
        MMpush (m, NIL);
404
        return 0;
405
    }
406
    mfile = MTOP (mfile);
407

  
408
    result = g_stat (MMstartstr (m, mfile), s);
409
    if (result != 0)
410
    {
411
        MMpush (m, NIL);
412
        return 0;
413
    }
414
    MMpush (m, ITOM (s->st_size));
415
    MMpush (m, ITOM (s->st_atime));
416
    MMpush (m, ITOM (s->st_mtime));
417
    MMpush (m, ITOM (s->st_ctime));
418
    MMpush (m, ITOM (4));
419
    MBdeftab (m);
420

  
421
    return 0;
422
}
423

  
424
/**
425
 * \brief _gbaseIsIp : Tests if a string is a form of an IPv4 or IPv6 address (like "123.210.012.231").
426
 * fun [S] I
427
 * \param S : any string
428
 * \return I : 1 if TRUE (the string is an IP address), 0 if FALSE
429
 */
430
int SCOL_gbaseIsIp (mmachine m)
431
{
432
    int ms;
433

  
434
    ms = MMpull (m);
435
    if (ms == NIL)
436
    {
437
        MMpush (m, NIL);
438
        return 0;
439
    }
440
    MMpush (m, ITOM (g_hostname_is_ip_address (MMstartstr (m, MTOP (ms)))));
441
    return 0;
442
}
443

  
444

  
445

  
446

  
447

  
448

  
449 449
/* API d?finitions : */
450 450

  
451 451
char* gbase_name[GBASE_PKG_NB]=
452 452
{
453
    "_gbaseUserName",

454
    "_gBaseHostName",

455
    "_gBaseDirCur",

456
    "_gBasePathAbsolute",

457
    "_gBasePathBase",

458
    "_gBasePathDir",

459
    "_gBasePathBuild",

460
    "_gBaseStringUTF8",

461
    "_gbaseChecksumS",

462
    "_gbaseChecksumP",

463
    "_gbaseSleep",

464
    "_gbaseFileStat",

453
    "_gbaseUserName",
454
    "_gBaseHostName",
455
    "_gBaseDirCur",
456
    "_gBasePathAbsolute",
457
    "_gBasePathBase",
458
    "_gBasePathDir",
459
    "_gBasePathBuild",
460
    "_gBaseStringUTF8",
461
    "_gbaseChecksumS",
462
    "_gbaseChecksumP",
463
    "_gbaseSleep",
464
    "_gbaseFileStat",
465 465
    "_gbaseIsIp"
466 466
};
467 467

  
468 468
int (*gbase_fun[GBASE_PKG_NB])(mmachine m)=
469 469
{
470
    SCOL_gbaseUserName,

471
    SCOL_gBaseHostName,

472
    SCOL_gBaseDirCur,

473
    SCOL_gBasePathAbsolute,

474
    SCOL_gBasePathBase,

475
    SCOL_gBasePathDir,

476
    SCOL_gBasePathBuild,

477
    SCOL_gBaseStringUTF8,

478
    SCOL_gbaseChecksumS,

479
    SCOL_gbaseChecksumP,

480
    SCOL_gbaseSleep,

481
    SCOL_gbaseFileStat,

470
    SCOL_gbaseUserName,
471
    SCOL_gBaseHostName,
472
    SCOL_gBaseDirCur,
473
    SCOL_gBasePathAbsolute,
474
    SCOL_gBasePathBase,
475
    SCOL_gBasePathDir,
476
    SCOL_gBasePathBuild,
477
    SCOL_gBaseStringUTF8,
478
    SCOL_gbaseChecksumS,
479
    SCOL_gbaseChecksumP,
480
    SCOL_gbaseSleep,
481
    SCOL_gbaseFileStat,
482 482
    SCOL_gbaseIsIp
483 483
};
484 484

  
485 485
int gbase_narg[GBASE_PKG_NB]=
486 486
{
487
    0,      /* SCOL_gbaseUserName */

488
    0,      /* SCOL_gBaseHostName */

489
    0,      /* SCOL_gBaseDirCur */

490
    1,      /* SCOL_gBasePathAbsolute */

491
    1,      /* SCOL_gBasePathBase */

492
    1,      /* SCOL_gBasePathDir */

493
    2,      /* SCOL_gBasePathBuild */

494
    2,       /* SCOL_gBaseStringUTF8 */

495
    2,       /* SCOL_gbaseChecksumS */

496
    2,       /* SCOL_gbaseChecksumP */

497
    1,       /* SCOL_gbaseSleep */

498
    1,       /* SCOL_gbaseFileStat */

487
    0,      /* SCOL_gbaseUserName */
488
    0,      /* SCOL_gBaseHostName */
489
    0,      /* SCOL_gBaseDirCur */
490
    1,      /* SCOL_gBasePathAbsolute */
491
    1,      /* SCOL_gBasePathBase */
492
    1,      /* SCOL_gBasePathDir */
493
    2,      /* SCOL_gBasePathBuild */
494
    2,       /* SCOL_gBaseStringUTF8 */
495
    2,       /* SCOL_gbaseChecksumS */
496
    2,       /* SCOL_gbaseChecksumP */
497
    1,       /* SCOL_gbaseSleep */
498
    1,       /* SCOL_gbaseFileStat */
499 499
    1       /* SCOL_gbaseIsIp */
500 500
};
501 501

  
502 502
char* gbase_type[GBASE_PKG_NB]=
503 503
{
504
    "fun [] S",                     /* SCOL_gbaseUserName */

505
    "fun [] S",                     /* SCOL_gBaseHostName */

506
    "fun [] S",                     /* SCOL_gBaseDirCur */

507
    "fun [S] I",                    /* SCOL_gBasePathAbsolute */

508
    "fun [S] S",                    /* SCOL_gBasePathBase */

509
    "fun [S] S",                    /* SCOL_gBasePathDir */

510
    "fun [[S r1] I] S",             /* SCOL_gBasePathBuild */

511
    "fun [S I] S",                  /* SCOL_gBaseStringUTF8 */

512
    "fun [S I] S",                  /* SCOL_gbaseChecksumS */

513
    "fun [P I] S",                  /* SCOL_gbaseChecksumS */

514
    "fun [I] I",                    /* SCOL_gbaseSleep */

515
    "fun [P] [I I I I]",            /* SCOL_gbaseFileStat */

504
    "fun [] S",                     /* SCOL_gbaseUserName */
505
    "fun [] S",                     /* SCOL_gBaseHostName */
506
    "fun [] S",                     /* SCOL_gBaseDirCur */
507
    "fun [S] I",                    /* SCOL_gBasePathAbsolute */
508
    "fun [S] S",                    /* SCOL_gBasePathBase */
509
    "fun [S] S",                    /* SCOL_gBasePathDir */
510
    "fun [[S r1] I] S",             /* SCOL_gBasePathBuild */
511
    "fun [S I] S",                  /* SCOL_gBaseStringUTF8 */
512
    "fun [S I] S",                  /* SCOL_gbaseChecksumS */
513
    "fun [P I] S",                  /* SCOL_gbaseChecksumS */
514
    "fun [I] I",                    /* SCOL_gbaseSleep */
515
    "fun [P] [I I I I]",            /* SCOL_gbaseFileStat */
516 516
    "fun [S] I"                    /* SCOL_gbaseIsIp */
517 517
};
518 518

  
......
524 524

  
525 525
    k = PKhardpak (m, "GBaseEngine", GBASE_PKG_NB, gbase_name, gbase_fun, gbase_narg, gbase_type);
526 526
    return k;
527
}
528

  
529

  
530
/*
531
 * Load and free the regular expression library
532
 * Plateforms supported : MS Windows and GNU / Linux
533
 */
534

  
535
int GBaseRelease ()
536
{
537
    MMechostr (0, "\nGBASE library released !\n");
538
    return 0;
539
}
540

  
541
#if ((defined _WIN32) || (defined __WIN32__))
542

  
543
__declspec (dllexport) int SCOLloadGBASE (mmachine m, cbmachine w)
544
{
545
    int k = 0;
546
    ww = w;
547
    mm = m;
548

  
549
    MMechostr (MSKDEBUG, "\nGBASE library loading .... !\n");
550
    SCOLinitplugin (w);
551
    if ((k = SCOLinitGbaseClass (m))) return k;
552
    MMechostr(MSKDEBUG, "\nGBASE library loaded !\n");
553
    return k;
554
}
555

  
556
__declspec (dllexport) int SCOLfreeGBASE ()
557
{
558
    GBaseRelease ();
559
    return 0;
560
}
561

  
562

  
563

  
564

  
565

  
566
/* Version GNU / Linux */
567
#elif ((defined linux) || (defined __linux))
568

  
569
int SCOLloadGBASE (mmachine m)
570
{
571
    int k = 0;
572
    mm = m;
573

  
574
    MMechostr (MSKDEBUG, "\nGBASE library loading !\n");
575
    if ((k = SCOLinitGbaseClass (m))) return k;
576
    MMechostr (MSKDEBUG, "\nGBASE library loaded !\n");
577

  
578
    return k;
579
}
580

  
581
int SCOLfreeGBASE ()
582
{
583
    GBaseRelease ();
584
    return 0;
585
}
586

  
587
#else
588
#error no platform supported
589
#endif
590

  
527
}
528

  
529

  
530
/*
531
 * Load and free the regular expression library
532
 * Plateforms supported : MS Windows and GNU / Linux
533
 */
534

  
535
int GBaseRelease ()
536
{
537
    MMechostr (0, "\nGBASE library released !\n");
538
    return 0;
539
}
540

  
541
#if ((defined _WIN32) || (defined __WIN32__))
542

  
543
__declspec (dllexport) int SCOLloadGBASE (mmachine m, cbmachine w)
544
{
545
    int k = 0;
546
    ww = w;
547
    mm = m;
548

  
549
    MMechostr (MSKDEBUG, "\nGBASE library loading .... !\n");
550
    SCOLinitplugin (w);
551
    if ((k = SCOLinitGbaseClass (m))) return k;
552
    MMechostr(MSKDEBUG, "\nGBASE library loaded !\n");
553
    return k;
554
}
555

  
556
__declspec (dllexport) int SCOLfreeGBASE ()
557
{
558
    GBaseRelease ();
559
    return 0;
560
}
561

  
562

  
563

  
564

  
565

  
566
/* Version GNU / Linux */
567
#elif ((defined linux) || (defined __linux))
568

  
569
int SCOLloadGBASE (mmachine m)
570
{
571
    int k = 0;
572
    mm = m;
573

  
574
    MMechostr (MSKDEBUG, "\nGBASE library loading !\n");
575
    if ((k = SCOLinitGbaseClass (m))) return k;
576
    MMechostr (MSKDEBUG, "\nGBASE library loaded !\n");
577

  
578
    return k;
579
}
580

  
581
int SCOLfreeGBASE ()
582
{
583
    GBaseRelease ();
584
    return 0;
585
}
586

  
587
#else
588
#error no platform supported
589
#endif
590

  
src/scol_glib_keyfile.c
23 23
http://www.gnu.org/copyleft/lesser.txt
24 24

  
25 25
For others informations, please contact us from http://www.scolring.org/
26
*/

27

  
28
#include "../include/scol_glib_keyfile.h"

29

  
30
#if ((defined _WIN32) || (defined __WIN32__))

31
cbmachine ww;

32
#endif

33
mmachine  mm;

34

  
35

  
36
/**

37
 * \brief GKF_VALUE_RAW : I : flag used to load a key file. The raw value associated with key under group.

38
 * The value can be escaped string

39
 */

40
int GKF_VALUE_RAW (mmachine m) { return MMpush (m, ITOM (1)); }

41
/**

42
 * \brief GKF_VALUE_STRING : I : flag used to load a key file. The string value associated with key under group.

43
 * Unlike GKF_VALUE_RAW, any escaped sequence are unescaped

44
 */

45
int GKF_VALUE_STRING (mmachine m) { return MMpush (m, ITOM (2)); }

46
/**

47
 * \brief GKF_VALUE_INTEGER : Not implemented yet

48
 */

49
int GKF_VALUE_INTEGER (mmachine m) { return MMpush (m, ITOM (3)); }

50
/**

51
 * \brief GKF_VALUE_INTEGER64 : Not implemented yet

52
 */

53
int GKF_VALUE_INTEGER64 (mmachine m) { return MMpush (m, ITOM (4)); }

54
/**

55
 * \brief GKF_VALUE_UINTEGER64 : Not implemented yet

56
 */

57
int GKF_VALUE_UINTEGER64 (mmachine m) { return MMpush (m, ITOM (5)); }

58
/**

59
 * \brief GKF_VALUE_DOUBLE : Not implemented yet

60
 */

61
int GKF_VALUE_DOUBLE (mmachine m) { return MMpush (m, ITOM (6)); }

62
/**

63
 * \brief GKF_VALUE_BOOLEAN : Not implemented yet

64
 */

65
int GKF_VALUE_BOOLEAN (mmachine m) { return MMpush (m, ITOM (7)); }

66

  
67

  
68
/**

69
 * \brief _gkeyFileReadP : read a key file

70
 * fun [P S] [[S [[S S] r1]] r1]

71
 *

72
 * \param P : any file (read reference only)

73
 * \param S : the list seperator, or nil (default ";")

74
 * \return [[S [[S S] r1]] r1] : the list of datas : group names and for each group name, a list of tuple [key value]

75
 */

76
int SCOL_gkeyFileReadP (mmachine m)

77
{

78
    int mfile, msep;

79
    gboolean b;

80
    GKeyFile *ini;

81
    GError *err = NULL;

82

  
83
    msep = MTOP (MMpull (m));

84
    mfile = MMpull (m);

85
    if (mfile == NIL)

86
    {

87
        MMpush (m, NIL);

88
        return 0;

89
    }

90

  
91
    ini = g_key_file_new ();

92
    if (msep != NIL)

93
        g_key_file_set_list_separator (ini, (MMstart (m, msep))[0]);

94
    b = g_key_file_load_from_file (ini, MMstartstr (m, MTOP (mfile)), G_KEY_FILE_NONE, &err);

95
    if (!b)

96
    {

97
        MMechostr (0, "SCOL_gkeyFileReadP load error : %d .:. %s\n", err->code, err->message);

98
        g_error_free (err);

99
        MMpush (m, NIL);

100
        return 0;

101
    }

102
    g_key_file_free (ini);

103
    return scol_g_key_file_read (ini, m);

104
}

105

  
106

  
107

  
108

  
109

  
110

  
111

  
112

  
113
/* ========================================================================= */

114

  
115

  
26
*/
27

  
28
#include "../include/scol_glib_keyfile.h"
29

  
30
#if ((defined _WIN32) || (defined __WIN32__))
31
cbmachine ww;
32
#endif
33
mmachine  mm;
34

  
35

  
36
/**
37
 * \brief GKF_VALUE_RAW : I : flag used to load a key file. The raw value associated with key under group.
38
 * The value can be escaped string
39
 */
40
int GKF_VALUE_RAW (mmachine m) { return MMpush (m, ITOM (1)); }
41
/**
42
 * \brief GKF_VALUE_STRING : I : flag used to load a key file. The string value associated with key under group.
43
 * Unlike GKF_VALUE_RAW, any escaped sequence are unescaped
44
 */
45
int GKF_VALUE_STRING (mmachine m) { return MMpush (m, ITOM (2)); }
46
/**
47
 * \brief GKF_VALUE_INTEGER : Not implemented yet
48
 */
49
int GKF_VALUE_INTEGER (mmachine m) { return MMpush (m, ITOM (3)); }
50
/**
51
 * \brief GKF_VALUE_INTEGER64 : Not implemented yet
52
 */
53
int GKF_VALUE_INTEGER64 (mmachine m) { return MMpush (m, ITOM (4)); }
54
/**
55
 * \brief GKF_VALUE_UINTEGER64 : Not implemented yet
56
 */
57
int GKF_VALUE_UINTEGER64 (mmachine m) { return MMpush (m, ITOM (5)); }
58
/**
59
 * \brief GKF_VALUE_DOUBLE : Not implemented yet
60
 */
61
int GKF_VALUE_DOUBLE (mmachine m) { return MMpush (m, ITOM (6)); }
62
/**
63
 * \brief GKF_VALUE_BOOLEAN : Not implemented yet
64
 */
65
int GKF_VALUE_BOOLEAN (mmachine m) { return MMpush (m, ITOM (7)); }
66

  
67

  
68
/**
69
 * \brief _gkeyFileReadP : read a key file
70
 * fun [P S] [[S [[S S] r1]] r1]
71
 *
72
 * \param P : any file (read reference only)
73
 * \param S : the list seperator, or nil (default ";")
74
 * \return [[S [[S S] r1]] r1] : the list of datas = group names and for each group name, a list of tuple [key value]
75
 */
76
int SCOL_gkeyFileReadP (mmachine m)
77
{
78
    int mfile, msep;
79
    gboolean b;
80
    GKeyFile *ini;
81
    GError *err = NULL;
82

  
83
    msep = MTOP (MMpull (m));
84
    mfile = MMpull (m);
85
    if (mfile == NIL)
86
    {
87
        MMpush (m, NIL);
88
        return 0;
89
    }
90

  
91
    ini = g_key_file_new ();
92
    if (msep != NIL)
93
        g_key_file_set_list_separator (ini, (MMstart (m, msep))[0]);
94
    b = g_key_file_load_from_file (ini, MMstartstr (m, MTOP (mfile)), G_KEY_FILE_NONE, &err);
95
    if (!b)
96
    {
97
        MMechostr (0, "SCOL_gkeyFileReadP load error : %d .:. %s\n", err->code, err->message);
98
        g_error_free (err);
99
        MMpush (m, NIL);
100
        return 0;
101
    }
102
    g_key_file_free (ini);
103
    return scol_g_key_file_read (ini, m);
104
}
105

  
106

  
107

  
108

  
109

  
110

  
111

  
112

  
113
/* ========================================================================= */
114

  
115

  
116 116
/** \private
117 117
 * internal function : get groups names
118
 */

119
int scol_g_key_file_get_groups (mmachine m, int flag)

120
{

121
    int mini;

122
    int i = 0;

123
    gsize len = 0;

124
    GKeyFile *ini;

125
    gchar **groups;

126

  
127
    mini = MMpull (m);

128
    if (mini == NIL)

129
    {

118
 */
119
int scol_g_key_file_get_groups (mmachine m, int flag)
120
{
121
    int mini;
122
    int i = 0;
123
    gsize len = 0;
124
    GKeyFile *ini;
125
    gchar **groups;
126

  
127
    mini = MMpull (m);
128
    if (mini == NIL)
129
    {
130 130
        MMechostr (0, "scol_g_key_file_get_groups error : object is nil\n");
131
        MMpush (m, NIL);

132
        return 0;

133
    }

134

  
135
    ini = (GKeyFile*) MMfetch (m, MTOP (mini), OBJGKEYFILE_HANDLE);

136
    groups = g_key_file_get_groups (ini, &len);

137
    if (flag)

138
        MMpush (m, ITOM ((int) len));   /* I */

139
    else

140
    {

141
        for (i = 0; i < (int) len; i++)

142
            Mpushstrbloc (m, groups[i]);

143
        MMpush (m, NIL);

144
        for (i = 0; i < (int) len; i++)

145
        {

146
            MMpush (m, ITOM (2));

147
            MBdeftab (m);

148
        }                               /* [S r1] */

149
    }

150
    g_strfreev (groups);

151
    return 0;

152
}

131
        MMpush (m, NIL);
132
        return 0;
133
    }
134

  
135
    ini = (GKeyFile*) MMfetch (m, MTOP (mini), OBJGKEYFILE_HANDLE);
136
    groups = g_key_file_get_groups (ini, &len);
137
    if (flag)
138
        MMpush (m, ITOM ((int) len));   /* I */
139
    else
140
    {
141
        for (i = 0; i < (int) len; i++)
142
            Mpushstrbloc (m, groups[i]);
143
        MMpush (m, NIL);
144
        for (i = 0; i < (int) len; i++)
145
        {
146
            MMpush (m, ITOM (2));
147
            MBdeftab (m);
148
        }                               /* [S r1] */
149
    }
150
    g_strfreev (groups);
151
    return 0;
152
}
153 153
/** \private
154 154
 * internal function : return a list of the entire content ( [[S [[S S] r1]] r1] )
155
 */

156
int scol_g_key_file_read (GKeyFile *ini, mmachine m)

157
{

158
    int i, j;

159
    gsize ngroups, nkeys;

160
    gchar **groups;

161

  
162
    groups = g_key_file_get_groups (ini, &ngroups);

163
    for (i = 0; i < (int) ngroups; i++)

164
    {

165
        gchar **keys;

166

  
167
        Mpushstrbloc (m, groups[i]);    /* S */

168

  
169
        keys = g_key_file_get_keys (ini, groups[i], &nkeys, NULL);

170
        for (j = 0; j < (int) nkeys; j++)

171
        {

172
            gchar *value;

173

  
174
            value = g_key_file_get_value (ini, groups[i], keys[j], NULL);

175
            Mpushstrbloc (m, keys[j]);

176
            Mpushstrbloc (m, value);

177
            MMpush (m, ITOM (2));

178
            MBdeftab (m);               /* [S S] */

179
            g_free (value);

180
        }

181
        g_strfreev (keys);

182
        MMpush (m, NIL);

183
        for (j = 0; j < (int) nkeys; j++)

184
        {

185
            MMpush (m, ITOM (2));

186
            MBdeftab (m);

187
        }                               /* [[S S] r1] */

188
        MMpush (m, ITOM (2));

189
        MBdeftab (m);                   /* [S [[S S] r1]] */

190
    }

191
    g_strfreev (groups);

192
    MMpush (m, NIL);

193
    for (i = 0; i < (int) ngroups; i++)

194
    {

195
        MMpush (m, ITOM (2));

196
        MBdeftab (m);

197
    }                                   /* [[S [[S S] r1]] r1] */

198
    return 0;

199
}

200

  
155
 */
156
int scol_g_key_file_read (GKeyFile *ini, mmachine m)
157
{
158
    int i, j;
159
    gsize ngroups, nkeys;
160
    gchar **groups;
161

  
162
    groups = g_key_file_get_groups (ini, &ngroups);
163
    for (i = 0; i < (int) ngroups; i++)
164
    {
165
        gchar **keys;
166

  
167
        Mpushstrbloc (m, groups[i]);    /* S */
168

  
169
        keys = g_key_file_get_keys (ini, groups[i], &nkeys, NULL);
170
        for (j = 0; j < (int) nkeys; j++)
171
        {
172
            gchar *value;
173

  
174
            value = g_key_file_get_value (ini, groups[i], keys[j], NULL);
175
            Mpushstrbloc (m, keys[j]);
176
            Mpushstrbloc (m, value);
177
            MMpush (m, ITOM (2));
178
            MBdeftab (m);               /* [S S] */
179
            g_free (value);
180
        }
181
        g_strfreev (keys);
182
        MMpush (m, NIL);
183
        for (j = 0; j < (int) nkeys; j++)
184
        {
185
            MMpush (m, ITOM (2));
186
            MBdeftab (m);
187
        }                               /* [[S S] r1] */
188
        MMpush (m, ITOM (2));
189
        MBdeftab (m);                   /* [S [[S S] r1]] */
190
    }
191
    g_strfreev (groups);
192
    MMpush (m, NIL);
193
    for (i = 0; i < (int) ngroups; i++)
194
    {
195
        MMpush (m, ITOM (2));
196
        MBdeftab (m);
197
    }                                   /* [[S [[S S] r1]] r1] */
198
    return 0;
199
}
200

  
201 201
/** \private
202 202
 * internal function : load a file or data
203
 */
204
int scol_g_key_file_load (mmachine m, int typ)
205
{
206
    int mchannel, mfile, msep, mflag;
207
    int initab;
208
    gboolean b;
209
    GKeyFileFlags flag = G_KEY_FILE_NONE;
210
    GKeyFile *ini;
211
    GError *err = NULL;
212

  
213
    mflag = MTOI (MMpull (m));
214
    msep = MTOP (MMpull (m));
215
    mfile = MMpull (m);
216
    mchannel = MMget (m, 0);
217

  
218
    if (mchannel == NIL)
219
    {
220
        MMechostr (0, "scol_g_key_file_load error : channel is nil\n");
221
        MMpush (m, NIL);
222
        return 0;
223
    }
224
    if (mfile == NIL)
225
    {
226
        MMechostr (0, "scol_g_key_file_load error : file is nil\n");
227
        MMpush (m, NIL);
228
        return 0;
229
    }
230

  
231
    ini = g_key_file_new ();
232
    if (msep != NIL)
233
        g_key_file_set_list_separator (ini, (MMstart (m, msep))[0]);
234

  
235
    if (mflag == 1)
236
        flag = G_KEY_FILE_KEEP_COMMENTS;
237
    else if (mflag == 2)
238
        flag = G_KEY_FILE_KEEP_TRANSLATIONS;
239
    else if (mflag == 3)
240
        flag = G_KEY_FILE_KEEP_TRANSLATIONS|G_KEY_FILE_KEEP_COMMENTS;
241

  
242
    if (typ)
243
        b = g_key_file_load_from_data (ini, MMstartstr (m, MTOP (mfile)), MMsizestr (m, MTOP (mfile)), flag, &err);
244
    else
245
        b = g_key_file_load_from_file (ini, MMstartstr (m, MTOP (mfile)), flag, &err);
246
    if ((!b) || (err != NULL))
247
    {
248
        MMechostr (0, "scol_g_key_file_load error : loading is failed -> %s\n", err->message);
249
        g_error_free (err);
250
        MMpush (m, NIL);
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff