summaryrefslogtreecommitdiff
path: root/strlib.c
blob: a3467050d8532ca6ef0fc2bab00ca0920c2f1320 (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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/*
** strlib.c
** String library to LUA
*/

char *rcs_strlib="$Id: strlib.c,v 1.22 1996/03/22 17:57:24 roberto Exp roberto $";

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>

#include "lua.h"
#include "lualib.h"


void lua_arg_error(char *funcname)
{
  char buff[100];
  sprintf(buff, "incorrect arguments to function `%s'", funcname);
  lua_error(buff);
}

char *lua_check_string (int numArg, char *funcname)
{
  lua_Object o = lua_getparam(numArg);
  if (!lua_isstring(o))
    lua_arg_error(funcname);
  return lua_getstring(o);
}

double lua_check_number (int numArg, char *funcname)
{
  lua_Object o = lua_getparam(numArg);
  if (!lua_isnumber(o))
    lua_arg_error(funcname);
  return lua_getnumber(o);
}

static int lua_opt_number (int numArg, int def, char *funcname)
{
  return (lua_getparam(numArg) == LUA_NOOBJECT) ? def :
                              (int)lua_check_number(numArg, funcname);
}

char *luaI_addchar (int c)
{
  static char *buff = NULL;
  static int max = 0;
  static int n = 0;
  if (n >= max)
  {
    if (max == 0)
    {
      max = 100;
      buff = (char *)malloc(max);
    }
    else
    {
      max *= 2;
      buff = (char *)realloc(buff, max);
    }
    if (buff == NULL)
      lua_error("memory overflow");
  }
  buff[n++] = c;
  if (c == 0)
    n = 0;  /* prepare for next string */
  return buff;
}


/*
** Return the position of the first caracter of a substring into a string
** LUA interface:
**			n = strfind (string, substring, init, end)
*/
static void str_find (void)
{
 char *s1 = lua_check_string(1, "strfind");
 char *s2 = lua_check_string(2, "strfind");
 int init = lua_opt_number(3, 1, "strfind") - 1;
 char *f = (init>=0 && init<=strlen(s1)) ? strstr(s1+init,s2) : NULL;
 if (f != NULL)
 {
  int pos = f-s1+1;
  if (lua_opt_number(4, INT_MAX, "strfind") >= pos+strlen(s2)-1)
   lua_pushnumber (pos);
  else
   lua_pushnil();
 }
 else
  lua_pushnil();
}

/*
** Return the string length
** LUA interface:
**			n = strlen (string)
*/
static void str_len (void)
{
 char *s = lua_check_string(1, "strlen");
 lua_pushnumber(strlen(s));
}


/*
** Return the substring of a string, from start to end
** LUA interface:
**			substring = strsub (string, start, end)
*/
static void str_sub (void)
{
 char *s = lua_check_string(1, "strsub");
 int start = (int)lua_check_number(2, "strsub");
 int end = lua_opt_number(3, strlen(s), "strsub");
 if (end < start || start < 1 || end > strlen(s))
  lua_pushliteral("");
 else
 {
   luaI_addchar(0);
   while (start <= end) 
     luaI_addchar(s[start++ - 1]);
   lua_pushstring (luaI_addchar(0));
 }
}

/*
** Convert a string to lower case.
** LUA interface:
**			lowercase = strlower (string)
*/
static void str_lower (void)
{
  char *s = lua_check_string(1, "strlower");
  luaI_addchar(0);
  while (*s)
    luaI_addchar(tolower(*s++));
  lua_pushstring(luaI_addchar(0));
}


/*
** Convert a string to upper case.
** LUA interface:
**			uppercase = strupper (string)
*/
static void str_upper (void)
{
  char *s = lua_check_string(1, "strupper");
  luaI_addchar(0);
  while (*s)
    luaI_addchar(toupper(*s++));
  lua_pushstring(luaI_addchar(0));
}

/*
** get ascii value of a character in a string
*/
static void str_ascii (void)
{
  char *s = lua_check_string(1, "ascii");
  int pos = lua_opt_number(2, 1, "ascii") - 1;
  if (pos<0 || pos>=strlen(s))
    lua_arg_error("ascii");
  lua_pushnumber(s[pos]);
}

void luaI_addquoted (char *s)
{
  luaI_addchar('"');
  for (; *s; s++)
  {
    if (*s == '"' || *s == '\\' || *s == '\n')
      luaI_addchar('\\');
    luaI_addchar(*s);
  }
  luaI_addchar('"');
}

#define MAX_CONVERTION 2000
#define MAX_FORMAT 50

static void str_format (void)
{
  int arg = 1;
  char *strfrmt = lua_check_string(arg++, "format");
  luaI_addchar(0);  /* initialize */
  while (*strfrmt)
  {
    if (*strfrmt != '%')
      luaI_addchar(*strfrmt++);
    else if (*++strfrmt == '%')
      luaI_addchar(*strfrmt++);  /* %% */
    else
    { /* format item */
      char form[MAX_FORMAT];      /* store the format ('%...') */
      char buff[MAX_CONVERTION];  /* store the formated value */
      int size = 0;
      int i = 0;
      form[i++] = '%';
      form[i] = *strfrmt++;
      while (!isalpha(form[i]))
      {
        if (isdigit(form[i]))
        {
          size = size*10 + form[i]-'0';
          if (size >= MAX_CONVERTION)
            lua_error("format size/precision too long in function `format'");
        }
        else if (form[i] == '.')
          size = 0;  /* re-start */
        if (++i >= MAX_FORMAT)
            lua_error("bad format in function `format'");
        form[i] = *strfrmt++;
      }
      form[i+1] = 0;  /* ends string */
      switch (form[i])
      {
        case 'q':
          luaI_addquoted(lua_check_string(arg++, "format"));
          buff[0] = '\0';  /* addchar already done */
          break;
        case 's':
        {
          char *s = lua_check_string(arg++, "format");
          if (strlen(s) >= MAX_CONVERTION)
            lua_error("string argument too long in function `format'");
          sprintf(buff, form, s);
          break;
        }
        case 'c':  case 'd':  case 'i': case 'o':
        case 'u':  case 'x':  case 'X':
          sprintf(buff, form, (int)lua_check_number(arg++, "format"));
          break;
        case 'e':  case 'E': case 'f': case 'g':
          sprintf(buff, form, lua_check_number(arg++, "format"));
          break;
        default:  /* also treat cases 'pnLlh' */
          lua_error("invalid format option in function `format'");
      }
      for (i=0; buff[i]; i++)  /* move formated value to result */
        luaI_addchar(buff[i]);
    }
  }
  lua_pushstring(luaI_addchar(0));  /* push the result */
}


void luaI_openlib (struct lua_reg *l, int n)
{
  int i;
  for (i=0; i<n; i++)
    lua_register(l[i].name, l[i].func);
}

static struct lua_reg strlib[] = {
{"strfind", str_find},
{"strlen", str_len},
{"strsub", str_sub},
{"strlower", str_lower},
{"strupper", str_upper},
{"ascii", str_ascii},
{"format",    str_format}
};


/*
** Open string library
*/
void strlib_open (void)
{
  luaI_openlib(strlib, (sizeof(strlib)/sizeof(strlib[0])));
}