/PC/msvcrtmodule.c

http://unladen-swallow.googlecode.com/ · C · 337 lines · 251 code · 55 blank · 31 comment · 38 complexity · 63dbd9364cbb94afd21cf99e696c77fc MD5 · raw file

  1. /*********************************************************
  2. msvcrtmodule.c
  3. A Python interface to the Microsoft Visual C Runtime
  4. Library, providing access to those non-portable, but
  5. still useful routines.
  6. Only ever compiled with an MS compiler, so no attempt
  7. has been made to avoid MS language extensions, etc...
  8. This may only work on NT or 95...
  9. Author: Mark Hammond and Guido van Rossum.
  10. Maintenance: Guido van Rossum.
  11. ***********************************************************/
  12. #include "Python.h"
  13. #include "malloc.h"
  14. #include <io.h>
  15. #include <conio.h>
  16. #include <sys/locking.h>
  17. #ifdef _MSC_VER
  18. #if _MSC_VER >= 1500
  19. #include <crtassem.h>
  20. #endif
  21. #endif
  22. // Force the malloc heap to clean itself up, and free unused blocks
  23. // back to the OS. (According to the docs, only works on NT.)
  24. static PyObject *
  25. msvcrt_heapmin(PyObject *self, PyObject *args)
  26. {
  27. if (!PyArg_ParseTuple(args, ":heapmin"))
  28. return NULL;
  29. if (_heapmin() != 0)
  30. return PyErr_SetFromErrno(PyExc_IOError);
  31. Py_INCREF(Py_None);
  32. return Py_None;
  33. }
  34. // Perform locking operations on a C runtime file descriptor.
  35. static PyObject *
  36. msvcrt_locking(PyObject *self, PyObject *args)
  37. {
  38. int fd;
  39. int mode;
  40. long nbytes;
  41. int err;
  42. if (!PyArg_ParseTuple(args, "iil:locking", &fd, &mode, &nbytes))
  43. return NULL;
  44. Py_BEGIN_ALLOW_THREADS
  45. err = _locking(fd, mode, nbytes);
  46. Py_END_ALLOW_THREADS
  47. if (err != 0)
  48. return PyErr_SetFromErrno(PyExc_IOError);
  49. Py_INCREF(Py_None);
  50. return Py_None;
  51. }
  52. // Set the file translation mode for a C runtime file descriptor.
  53. static PyObject *
  54. msvcrt_setmode(PyObject *self, PyObject *args)
  55. {
  56. int fd;
  57. int flags;
  58. if (!PyArg_ParseTuple(args,"ii:setmode", &fd, &flags))
  59. return NULL;
  60. flags = _setmode(fd, flags);
  61. if (flags == -1)
  62. return PyErr_SetFromErrno(PyExc_IOError);
  63. return PyInt_FromLong(flags);
  64. }
  65. // Convert an OS file handle to a C runtime file descriptor.
  66. static PyObject *
  67. msvcrt_open_osfhandle(PyObject *self, PyObject *args)
  68. {
  69. long handle;
  70. int flags;
  71. int fd;
  72. if (!PyArg_ParseTuple(args, "li:open_osfhandle", &handle, &flags))
  73. return NULL;
  74. fd = _open_osfhandle(handle, flags);
  75. if (fd == -1)
  76. return PyErr_SetFromErrno(PyExc_IOError);
  77. return PyInt_FromLong(fd);
  78. }
  79. // Convert a C runtime file descriptor to an OS file handle.
  80. static PyObject *
  81. msvcrt_get_osfhandle(PyObject *self, PyObject *args)
  82. {
  83. int fd;
  84. Py_intptr_t handle;
  85. if (!PyArg_ParseTuple(args,"i:get_osfhandle", &fd))
  86. return NULL;
  87. handle = _get_osfhandle(fd);
  88. if (handle == -1)
  89. return PyErr_SetFromErrno(PyExc_IOError);
  90. /* technically 'handle' is not a pointer, but a integer as
  91. large as a pointer, Python's *VoidPtr interface is the
  92. most appropriate here */
  93. return PyLong_FromVoidPtr((void*)handle);
  94. }
  95. /* Console I/O */
  96. static PyObject *
  97. msvcrt_kbhit(PyObject *self, PyObject *args)
  98. {
  99. int ok;
  100. if (!PyArg_ParseTuple(args, ":kbhit"))
  101. return NULL;
  102. ok = _kbhit();
  103. return PyInt_FromLong(ok);
  104. }
  105. static PyObject *
  106. msvcrt_getch(PyObject *self, PyObject *args)
  107. {
  108. int ch;
  109. char s[1];
  110. if (!PyArg_ParseTuple(args, ":getch"))
  111. return NULL;
  112. Py_BEGIN_ALLOW_THREADS
  113. ch = _getch();
  114. Py_END_ALLOW_THREADS
  115. s[0] = ch;
  116. return PyString_FromStringAndSize(s, 1);
  117. }
  118. #ifdef _WCONIO_DEFINED
  119. static PyObject *
  120. msvcrt_getwch(PyObject *self, PyObject *args)
  121. {
  122. Py_UNICODE ch;
  123. Py_UNICODE u[1];
  124. if (!PyArg_ParseTuple(args, ":getwch"))
  125. return NULL;
  126. Py_BEGIN_ALLOW_THREADS
  127. ch = _getwch();
  128. Py_END_ALLOW_THREADS
  129. u[0] = ch;
  130. return PyUnicode_FromUnicode(u, 1);
  131. }
  132. #endif
  133. static PyObject *
  134. msvcrt_getche(PyObject *self, PyObject *args)
  135. {
  136. int ch;
  137. char s[1];
  138. if (!PyArg_ParseTuple(args, ":getche"))
  139. return NULL;
  140. Py_BEGIN_ALLOW_THREADS
  141. ch = _getche();
  142. Py_END_ALLOW_THREADS
  143. s[0] = ch;
  144. return PyString_FromStringAndSize(s, 1);
  145. }
  146. #ifdef _WCONIO_DEFINED
  147. static PyObject *
  148. msvcrt_getwche(PyObject *self, PyObject *args)
  149. {
  150. Py_UNICODE ch;
  151. Py_UNICODE s[1];
  152. if (!PyArg_ParseTuple(args, ":getwche"))
  153. return NULL;
  154. Py_BEGIN_ALLOW_THREADS
  155. ch = _getwche();
  156. Py_END_ALLOW_THREADS
  157. s[0] = ch;
  158. return PyUnicode_FromUnicode(s, 1);
  159. }
  160. #endif
  161. static PyObject *
  162. msvcrt_putch(PyObject *self, PyObject *args)
  163. {
  164. char ch;
  165. if (!PyArg_ParseTuple(args, "c:putch", &ch))
  166. return NULL;
  167. _putch(ch);
  168. Py_INCREF(Py_None);
  169. return Py_None;
  170. }
  171. #ifdef _WCONIO_DEFINED
  172. static PyObject *
  173. msvcrt_putwch(PyObject *self, PyObject *args)
  174. {
  175. Py_UNICODE *ch;
  176. int size;
  177. if (!PyArg_ParseTuple(args, "u#:putwch", &ch, &size))
  178. return NULL;
  179. if (size == 0) {
  180. PyErr_SetString(PyExc_ValueError,
  181. "Expected unicode string of length 1");
  182. return NULL;
  183. }
  184. _putwch(*ch);
  185. Py_RETURN_NONE;
  186. }
  187. #endif
  188. static PyObject *
  189. msvcrt_ungetch(PyObject *self, PyObject *args)
  190. {
  191. char ch;
  192. if (!PyArg_ParseTuple(args, "c:ungetch", &ch))
  193. return NULL;
  194. if (_ungetch(ch) == EOF)
  195. return PyErr_SetFromErrno(PyExc_IOError);
  196. Py_INCREF(Py_None);
  197. return Py_None;
  198. }
  199. #ifdef _WCONIO_DEFINED
  200. static PyObject *
  201. msvcrt_ungetwch(PyObject *self, PyObject *args)
  202. {
  203. Py_UNICODE ch;
  204. if (!PyArg_ParseTuple(args, "u:ungetwch", &ch))
  205. return NULL;
  206. if (_ungetch(ch) == EOF)
  207. return PyErr_SetFromErrno(PyExc_IOError);
  208. Py_INCREF(Py_None);
  209. return Py_None;
  210. }
  211. #endif
  212. static void
  213. insertint(PyObject *d, char *name, int value)
  214. {
  215. PyObject *v = PyInt_FromLong((long) value);
  216. if (v == NULL) {
  217. /* Don't bother reporting this error */
  218. PyErr_Clear();
  219. }
  220. else {
  221. PyDict_SetItemString(d, name, v);
  222. Py_DECREF(v);
  223. }
  224. }
  225. /* List of functions exported by this module */
  226. static struct PyMethodDef msvcrt_functions[] = {
  227. {"heapmin", msvcrt_heapmin, METH_VARARGS},
  228. {"locking", msvcrt_locking, METH_VARARGS},
  229. {"setmode", msvcrt_setmode, METH_VARARGS},
  230. {"open_osfhandle", msvcrt_open_osfhandle, METH_VARARGS},
  231. {"get_osfhandle", msvcrt_get_osfhandle, METH_VARARGS},
  232. {"kbhit", msvcrt_kbhit, METH_VARARGS},
  233. {"getch", msvcrt_getch, METH_VARARGS},
  234. {"getche", msvcrt_getche, METH_VARARGS},
  235. {"putch", msvcrt_putch, METH_VARARGS},
  236. {"ungetch", msvcrt_ungetch, METH_VARARGS},
  237. #ifdef _WCONIO_DEFINED
  238. {"getwch", msvcrt_getwch, METH_VARARGS},
  239. {"getwche", msvcrt_getwche, METH_VARARGS},
  240. {"putwch", msvcrt_putwch, METH_VARARGS},
  241. {"ungetwch", msvcrt_ungetwch, METH_VARARGS},
  242. #endif
  243. {NULL, NULL}
  244. };
  245. PyMODINIT_FUNC
  246. initmsvcrt(void)
  247. {
  248. int st;
  249. PyObject *d;
  250. PyObject *m = Py_InitModule("msvcrt", msvcrt_functions);
  251. if (m == NULL)
  252. return;
  253. d = PyModule_GetDict(m);
  254. /* constants for the locking() function's mode argument */
  255. insertint(d, "LK_LOCK", _LK_LOCK);
  256. insertint(d, "LK_NBLCK", _LK_NBLCK);
  257. insertint(d, "LK_NBRLCK", _LK_NBRLCK);
  258. insertint(d, "LK_RLCK", _LK_RLCK);
  259. insertint(d, "LK_UNLCK", _LK_UNLCK);
  260. /* constants for the crt versions */
  261. #ifdef _VC_ASSEMBLY_PUBLICKEYTOKEN
  262. st = PyModule_AddStringConstant(m, "VC_ASSEMBLY_PUBLICKEYTOKEN",
  263. _VC_ASSEMBLY_PUBLICKEYTOKEN);
  264. if (st < 0)return;
  265. #endif
  266. #ifdef _CRT_ASSEMBLY_VERSION
  267. st = PyModule_AddStringConstant(m, "CRT_ASSEMBLY_VERSION",
  268. _CRT_ASSEMBLY_VERSION);
  269. if (st < 0)return;
  270. #endif
  271. #ifdef __LIBRARIES_ASSEMBLY_NAME_PREFIX
  272. st = PyModule_AddStringConstant(m, "LIBRARIES_ASSEMBLY_NAME_PREFIX",
  273. __LIBRARIES_ASSEMBLY_NAME_PREFIX);
  274. if (st < 0)return;
  275. #endif
  276. }