1
2/* Error handling */
3
4#include "Python.h"
5
6#ifndef __STDC__
7#ifndef MS_WINDOWS
8extern char *strerror(int);
9#endif
10#endif
11
12#ifdef MS_WINDOWS
13#include "windows.h"
14#include "winbase.h"
15#endif
16
17#include <ctype.h>
18
19#ifdef __cplusplus
20extern "C" {
21#endif
22
23
24void
25PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)
26{
27    PyThreadState *tstate = PyThreadState_GET();
28    PyObject *oldtype, *oldvalue, *oldtraceback;
29
30    if (traceback != NULL && !PyTraceBack_Check(traceback)) {
31        /* XXX Should never happen -- fatal error instead? */
32        /* Well, it could be None. */
33        Py_DECREF(traceback);
34        traceback = NULL;
35    }
36
37    /* Save these in locals to safeguard against recursive
38       invocation through Py_XDECREF */
39    oldtype = tstate->curexc_type;
40    oldvalue = tstate->curexc_value;
41    oldtraceback = tstate->curexc_traceback;
42
43    tstate->curexc_type = type;
44    tstate->curexc_value = value;
45    tstate->curexc_traceback = traceback;
46
47    Py_XDECREF(oldtype);
48    Py_XDECREF(oldvalue);
49    Py_XDECREF(oldtraceback);
50}
51
52void
53PyErr_SetObject(PyObject *exception, PyObject *value)
54{
55    Py_XINCREF(exception);
56    Py_XINCREF(value);
57    PyErr_Restore(exception, value, (PyObject *)NULL);
58}
59
60void
61PyErr_SetNone(PyObject *exception)
62{
63    PyErr_SetObject(exception, (PyObject *)NULL);
64}
65
66void
67PyErr_SetString(PyObject *exception, const char *string)
68{
69    PyObject *value = PyString_FromString(string);
70    PyErr_SetObject(exception, value);
71    Py_XDECREF(value);
72}
73
74
75PyObject *
76PyErr_Occurred(void)
77{
78    PyThreadState *tstate = PyThreadState_GET();
79
80    return tstate->curexc_type;
81}
82
83
84int
85PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)
86{
87    if (err == NULL || exc == NULL) {
88        /* maybe caused by "import exceptions" that failed early on */
89        return 0;
90    }
91    if (PyTuple_Check(exc)) {
92        Py_ssize_t i, n;
93        n = PyTuple_Size(exc);
94        for (i = 0; i < n; i++) {
95            /* Test recursively */
96             if (PyErr_GivenExceptionMatches(
97                 err, PyTuple_GET_ITEM(exc, i)))
98             {
99                 return 1;
100             }
101        }
102        return 0;
103    }
104    /* err might be an instance, so check its class. */
105    if (PyExceptionInstance_Check(err))
106        err = PyExceptionInstance_Class(err);
107
108    if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) {
109        int res = 0, reclimit;
110        PyObject *exception, *value, *tb;
111        PyErr_Fetch(&exception, &value, &tb);
112        /* Temporarily bump the recursion limit, so that in the most
113           common case PyObject_IsSubclass will not raise a recursion
114           error we have to ignore anyway.  Don't do it when the limit
115           is already insanely high, to avoid overflow */
116        reclimit = Py_GetRecursionLimit();
117        if (reclimit < (1 << 30))
118            Py_SetRecursionLimit(reclimit + 5);
119        res = PyObject_IsSubclass(err, exc);
120        Py_SetRecursionLimit(reclimit);
121        /* This function must not fail, so print the error here */
122        if (res == -1) {
123            PyErr_WriteUnraisable(err);
124            res = 0;
125        }
126        PyErr_Restore(exception, value, tb);
127        return res;
128    }
129
130    return err == exc;
131}
132
133
134int
135PyErr_ExceptionMatches(PyObject *exc)
136{
137    return PyErr_GivenExceptionMatches(PyErr_Occurred(), exc);
138}
139
140
141/* Used in many places to normalize a raised exception, including in
142   eval_code2(), do_raise(), and PyErr_Print()
143*/
144void
145PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
146{
147    PyObject *type = *exc;
148    PyObject *value = *val;
149    PyObject *inclass = NULL;
150    PyObject *initial_tb = NULL;
151    PyThreadState *tstate = NULL;
152
153    if (type == NULL) {
154        /* There was no exception, so nothing to do. */
155        return;
156    }
157
158    /* If PyErr_SetNone() was used, the value will have been actually
159       set to NULL.
160    */
161    if (!value) {
162        value = Py_None;
163        Py_INCREF(value);
164    }
165
166    if (PyExceptionInstance_Check(value))
167        inclass = PyExceptionInstance_Class(value);
168
169    /* Normalize the exception so that if the type is a class, the
170       value will be an instance.
171    */
172    if (PyExceptionClass_Check(type)) {
173        /* if the value was not an instance, or is not an instance
174           whose class is (or is derived from) type, then use the
175           value as an argument to instantiation of the type
176           class.
177        */
178        if (!inclass || !PyObject_IsSubclass(inclass, type)) {
179            PyObject *args, *res;
180
181            if (value == Py_None)
182                args = PyTuple_New(0);
183            else if (PyTuple_Check(value)) {
184                Py_INCREF(value);
185                args = value;
186            }
187            else
188                args = PyTuple_Pack(1, value);
189
190            if (args == NULL)
191                goto finally;
192            res = PyEval_CallObject(type, args);
193            Py_DECREF(args);
194            if (res == NULL)
195                goto finally;
196            Py_DECREF(value);
197            value = res;
198        }
199        /* if the class of the instance doesn't exactly match the
200           class of the type, believe the instance
201        */
202        else if (inclass != type) {
203            Py_DECREF(type);
204            type = inclass;
205            Py_INCREF(type);
206        }
207    }
208    *exc = type;
209    *val = value;
210    return;
211finally:
212    Py_DECREF(type);
213    Py_DECREF(value);
214    /* If the new exception doesn't set a traceback and the old
215       exception had a traceback, use the old traceback for the
216       new exception.  It's better than nothing.
217    */
218    initial_tb = *tb;
219    PyErr_Fetch(exc, val, tb);
220    if (initial_tb != NULL) {
221        if (*tb == NULL)
222            *tb = initial_tb;
223        else
224            Py_DECREF(initial_tb);
225    }
226    /* normalize recursively */
227    tstate = PyThreadState_GET();
228    if (++tstate->recursion_depth > Py_GetRecursionLimit()) {
229        --tstate->recursion_depth;
230        /* throw away the old exception and use the recursion error instead */
231        Py_INCREF(PyExc_RuntimeError);
232        Py_SETREF(*exc, PyExc_RuntimeError);
233        Py_INCREF(PyExc_RecursionErrorInst);
234        Py_SETREF(*val, PyExc_RecursionErrorInst);
235        /* just keeping the old traceback */
236        return;
237    }
238    PyErr_NormalizeException(exc, val, tb);
239    --tstate->recursion_depth;
240}
241
242
243void
244PyErr_Fetch(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)
245{
246    PyThreadState *tstate = PyThreadState_GET();
247
248    *p_type = tstate->curexc_type;
249    *p_value = tstate->curexc_value;
250    *p_traceback = tstate->curexc_traceback;
251
252    tstate->curexc_type = NULL;
253    tstate->curexc_value = NULL;
254    tstate->curexc_traceback = NULL;
255}
256
257void
258PyErr_Clear(void)
259{
260    PyErr_Restore(NULL, NULL, NULL);
261}
262
263/* Restore previously fetched exception if an exception is not set,
264   otherwise drop previously fetched exception.
265   Like _PyErr_ChainExceptions() in Python 3, but doesn't set the context.
266 */
267void
268_PyErr_ReplaceException(PyObject *exc, PyObject *val, PyObject *tb)
269{
270    if (exc == NULL)
271        return;
272
273    if (PyErr_Occurred()) {
274        Py_DECREF(exc);
275        Py_XDECREF(val);
276        Py_XDECREF(tb);
277    }
278    else {
279        PyErr_Restore(exc, val, tb);
280    }
281}
282
283/* Convenience functions to set a type error exception and return 0 */
284
285int
286PyErr_BadArgument(void)
287{
288    PyErr_SetString(PyExc_TypeError,
289                    "bad argument type for built-in operation");
290    return 0;
291}
292
293PyObject *
294PyErr_NoMemory(void)
295{
296    if (PyErr_ExceptionMatches(PyExc_MemoryError))
297        /* already current */
298        return NULL;
299
300    /* raise the pre-allocated instance if it still exists */
301    if (PyExc_MemoryErrorInst)
302        PyErr_SetObject(PyExc_MemoryError, PyExc_MemoryErrorInst);
303    else
304        /* this will probably fail since there's no memory and hee,
305           hee, we have to instantiate this class
306        */
307        PyErr_SetNone(PyExc_MemoryError);
308
309    return NULL;
310}
311
312PyObject *
313PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
314{
315    PyObject *v;
316    char *s;
317    int i = errno;
318#ifdef PLAN9
319    char errbuf[ERRMAX];
320#endif
321#ifdef MS_WINDOWS
322    char *s_buf = NULL;
323    char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */
324#endif
325#ifdef EINTR
326    if (i == EINTR && PyErr_CheckSignals())
327        return NULL;
328#endif
329#ifdef PLAN9
330    rerrstr(errbuf, sizeof errbuf);
331    s = errbuf;
332#else
333    if (i == 0)
334        s = "Error"; /* Sometimes errno didn't get set */
335    else
336#ifndef MS_WINDOWS
337        s = strerror(i);
338#else
339    {
340        /* Note that the Win32 errors do not lineup with the
341           errno error.  So if the error is in the MSVC error
342           table, we use it, otherwise we assume it really _is_
343           a Win32 error code
344        */
345        if (i > 0 && i < _sys_nerr) {
346            s = _sys_errlist[i];
347        }
348        else {
349            int len = FormatMessage(
350                FORMAT_MESSAGE_ALLOCATE_BUFFER |
351                FORMAT_MESSAGE_FROM_SYSTEM |
352                FORMAT_MESSAGE_IGNORE_INSERTS,
353                NULL,                   /* no message source */
354                i,
355                MAKELANGID(LANG_NEUTRAL,
356                           SUBLANG_DEFAULT),
357                           /* Default language */
358                (LPTSTR) &s_buf,
359                0,                      /* size not used */
360                NULL);                  /* no args */
361            if (len==0) {
362                /* Only ever seen this in out-of-mem
363                   situations */
364                sprintf(s_small_buf, "Windows Error 0x%X", i);
365                s = s_small_buf;
366                s_buf = NULL;
367            } else {
368                s = s_buf;
369                /* remove trailing cr/lf and dots */
370                while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
371                    s[--len] = '\0';
372            }
373        }
374    }
375#endif /* Unix/Windows */
376#endif /* PLAN 9*/
377    if (filenameObject != NULL)
378        v = Py_BuildValue("(isO)", i, s, filenameObject);
379    else
380        v = Py_BuildValue("(is)", i, s);
381    if (v != NULL) {
382        PyErr_SetObject(exc, v);
383        Py_DECREF(v);
384    }
385#ifdef MS_WINDOWS
386    LocalFree(s_buf);
387#endif
388    return NULL;
389}
390
391
392PyObject *
393PyErr_SetFromErrnoWithFilename(PyObject *exc, const char *filename)
394{
395    PyObject *name = filename ? PyString_FromString(filename) : NULL;
396    PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
397    Py_XDECREF(name);
398    return result;
399}
400
401#ifdef MS_WINDOWS
402PyObject *
403PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, const Py_UNICODE *filename)
404{
405    PyObject *name = filename ?
406                     PyUnicode_FromUnicode(filename, wcslen(filename)) :
407             NULL;
408    PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
409    Py_XDECREF(name);
410    return result;
411}
412#endif /* MS_WINDOWS */
413
414PyObject *
415PyErr_SetFromErrno(PyObject *exc)
416{
417    return PyErr_SetFromErrnoWithFilenameObject(exc, NULL);
418}
419
420#ifdef MS_WINDOWS
421/* Windows specific error code handling */
422PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
423    PyObject *exc,
424    int ierr,
425    PyObject *filenameObject)
426{
427    int len;
428    char *s;
429    char *s_buf = NULL; /* Free via LocalFree */
430    char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */
431    PyObject *v;
432    DWORD err = (DWORD)ierr;
433    if (err==0) err = GetLastError();
434    len = FormatMessage(
435        /* Error API error */
436        FORMAT_MESSAGE_ALLOCATE_BUFFER |
437        FORMAT_MESSAGE_FROM_SYSTEM |
438        FORMAT_MESSAGE_IGNORE_INSERTS,
439        NULL,           /* no message source */
440        err,
441        MAKELANGID(LANG_NEUTRAL,
442        SUBLANG_DEFAULT), /* Default language */
443        (LPTSTR) &s_buf,
444        0,              /* size not used */
445        NULL);          /* no args */
446    if (len==0) {
447        /* Only seen this in out of mem situations */
448        sprintf(s_small_buf, "Windows Error 0x%X", err);
449        s = s_small_buf;
450        s_buf = NULL;
451    } else {
452        s = s_buf;
453        /* remove trailing cr/lf and dots */
454        while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
455            s[--len] = '\0';
456    }
457    if (filenameObject != NULL)
458        v = Py_BuildValue("(isO)", err, s, filenameObject);
459    else
460        v = Py_BuildValue("(is)", err, s);
461    if (v != NULL) {
462        PyErr_SetObject(exc, v);
463        Py_DECREF(v);
464    }
465    LocalFree(s_buf);
466    return NULL;
467}
468
469PyObject *PyErr_SetExcFromWindowsErrWithFilename(
470    PyObject *exc,
471    int ierr,
472    const char *filename)
473{
474    PyObject *name = filename ? PyString_FromString(filename) : NULL;
475    PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
476                                                                 ierr,
477                                                                 name);
478    Py_XDECREF(name);
479    return ret;
480}
481
482PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename(
483    PyObject *exc,
484    int ierr,
485    const Py_UNICODE *filename)
486{
487    PyObject *name = filename ?
488                     PyUnicode_FromUnicode(filename, wcslen(filename)) :
489             NULL;
490    PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
491                                                                 ierr,
492                                                                 name);
493    Py_XDECREF(name);
494    return ret;
495}
496
497PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr)
498{
499    return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL);
500}
501
502PyObject *PyErr_SetFromWindowsErr(int ierr)
503{
504    return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError,
505                                                  ierr, NULL);
506}
507PyObject *PyErr_SetFromWindowsErrWithFilename(
508    int ierr,
509    const char *filename)
510{
511    PyObject *name = filename ? PyString_FromString(filename) : NULL;
512    PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
513                                                  PyExc_WindowsError,
514                                                  ierr, name);
515    Py_XDECREF(name);
516    return result;
517}
518
519PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename(
520    int ierr,
521    const Py_UNICODE *filename)
522{
523    PyObject *name = filename ?
524                     PyUnicode_FromUnicode(filename, wcslen(filename)) :
525             NULL;
526    PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
527                                                  PyExc_WindowsError,
528                                                  ierr, name);
529    Py_XDECREF(name);
530    return result;
531}
532#endif /* MS_WINDOWS */
533
534void
535_PyErr_BadInternalCall(const char *filename, int lineno)
536{
537    PyErr_Format(PyExc_SystemError,
538                 "%s:%d: bad argument to internal function",
539                 filename, lineno);
540}
541
542/* Remove the preprocessor macro for PyErr_BadInternalCall() so that we can
543   export the entry point for existing object code: */
544#undef PyErr_BadInternalCall
545void
546PyErr_BadInternalCall(void)
547{
548    PyErr_Format(PyExc_SystemError,
549                 "bad argument to internal function");
550}
551#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)
552
553
554
555PyObject *
556PyErr_Format(PyObject *exception, const char *format, ...)
557{
558    va_list vargs;
559    PyObject* string;
560
561#ifdef HAVE_STDARG_PROTOTYPES
562    va_start(vargs, format);
563#else
564    va_start(vargs);
565#endif
566
567    string = PyString_FromFormatV(format, vargs);
568    PyErr_SetObject(exception, string);
569    Py_XDECREF(string);
570    va_end(vargs);
571    return NULL;
572}
573
574
575
576PyObject *
577PyErr_NewException(char *name, PyObject *base, PyObject *dict)
578{
579    char *dot;
580    PyObject *modulename = NULL;
581    PyObject *classname = NULL;
582    PyObject *mydict = NULL;
583    PyObject *bases = NULL;
584    PyObject *result = NULL;
585    dot = strrchr(name, '.');
586    if (dot == NULL) {
587        PyErr_SetString(PyExc_SystemError,
588            "PyErr_NewException: name must be module.class");
589        return NULL;
590    }
591    if (base == NULL)
592        base = PyExc_Exception;
593    if (dict == NULL) {
594        dict = mydict = PyDict_New();
595        if (dict == NULL)
596            goto failure;
597    }
598    if (PyDict_GetItemString(dict, "__module__") == NULL) {
599        modulename = PyString_FromStringAndSize(name,
600                                             (Py_ssize_t)(dot-name));
601        if (modulename == NULL)
602            goto failure;
603        if (PyDict_SetItemString(dict, "__module__", modulename) != 0)
604            goto failure;
605    }
606    if (PyTuple_Check(base)) {
607        bases = base;
608        /* INCREF as we create a new ref in the else branch */
609        Py_INCREF(bases);
610    } else {
611        bases = PyTuple_Pack(1, base);
612        if (bases == NULL)
613            goto failure;
614    }
615    /* Create a real new-style class. */
616    result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO",
617                                   dot+1, bases, dict);
618  failure:
619    Py_XDECREF(bases);
620    Py_XDECREF(mydict);
621    Py_XDECREF(classname);
622    Py_XDECREF(modulename);
623    return result;
624}
625
626
627/* Create an exception with docstring */
628PyObject *
629PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict)
630{
631    int result;
632    PyObject *ret = NULL;
633    PyObject *mydict = NULL; /* points to the dict only if we create it */
634    PyObject *docobj;
635
636    if (dict == NULL) {
637        dict = mydict = PyDict_New();
638        if (dict == NULL) {
639            return NULL;
640        }
641    }
642
643    if (doc != NULL) {
644        docobj = PyString_FromString(doc);
645        if (docobj == NULL)
646            goto failure;
647        result = PyDict_SetItemString(dict, "__doc__", docobj);
648        Py_DECREF(docobj);
649        if (result < 0)
650            goto failure;
651    }
652
653    ret = PyErr_NewException(name, base, dict);
654  failure:
655    Py_XDECREF(mydict);
656    return ret;
657}
658
659
660/* Call when an exception has occurred but there is no way for Python
661   to handle it.  Examples: exception in __del__ or during GC. */
662void
663PyErr_WriteUnraisable(PyObject *obj)
664{
665    PyObject *f, *t, *v, *tb;
666    PyErr_Fetch(&t, &v, &tb);
667    f = PySys_GetObject("stderr");
668    if (f != NULL) {
669        PyFile_WriteString("Exception ", f);
670        if (t) {
671            PyObject* moduleName;
672            char* className;
673            assert(PyExceptionClass_Check(t));
674            className = PyExceptionClass_Name(t);
675            if (className != NULL) {
676                char *dot = strrchr(className, '.');
677                if (dot != NULL)
678                    className = dot+1;
679            }
680
681            moduleName = PyObject_GetAttrString(t, "__module__");
682            if (moduleName == NULL)
683                PyFile_WriteString("<unknown>", f);
684            else {
685                char* modstr = PyString_AsString(moduleName);
686                if (modstr &&
687                    strcmp(modstr, "exceptions") != 0)
688                {
689                    PyFile_WriteString(modstr, f);
690                    PyFile_WriteString(".", f);
691                }
692            }
693            if (className == NULL)
694                PyFile_WriteString("<unknown>", f);
695            else
696                PyFile_WriteString(className, f);
697            if (v && v != Py_None) {
698                PyFile_WriteString(": ", f);
699                if (PyFile_WriteObject(v, f, 0) < 0) {
700                    PyErr_Clear();
701                    PyFile_WriteString("<exception repr() failed>", f);
702                }
703            }
704            Py_XDECREF(moduleName);
705        }
706        PyFile_WriteString(" in ", f);
707        if (PyFile_WriteObject(obj, f, 0) < 0) {
708            PyErr_Clear();
709            PyFile_WriteString("<object repr() failed>", f);
710        }
711        PyFile_WriteString(" ignored\n", f);
712        PyErr_Clear(); /* Just in case */
713    }
714    Py_XDECREF(t);
715    Py_XDECREF(v);
716    Py_XDECREF(tb);
717}
718
719extern PyObject *PyModule_GetWarningsModule(void);
720
721
722/* Set file and line information for the current exception.
723   If the exception is not a SyntaxError, also sets additional attributes
724   to make printing of exceptions believe it is a syntax error. */
725
726void
727PyErr_SyntaxLocation(const char *filename, int lineno)
728{
729    PyObject *exc, *v, *tb, *tmp;
730
731    /* add attributes for the line number and filename for the error */
732    PyErr_Fetch(&exc, &v, &tb);
733    PyErr_NormalizeException(&exc, &v, &tb);
734    /* XXX check that it is, indeed, a syntax error. It might not
735     * be, though. */
736    tmp = PyInt_FromLong(lineno);
737    if (tmp == NULL)
738        PyErr_Clear();
739    else {
740        if (PyObject_SetAttrString(v, "lineno", tmp))
741            PyErr_Clear();
742        Py_DECREF(tmp);
743    }
744    if (filename != NULL) {
745        tmp = PyString_FromString(filename);
746        if (tmp == NULL)
747            PyErr_Clear();
748        else {
749            if (PyObject_SetAttrString(v, "filename", tmp))
750                PyErr_Clear();
751            Py_DECREF(tmp);
752        }
753
754        tmp = PyErr_ProgramText(filename, lineno);
755        if (tmp) {
756            if (PyObject_SetAttrString(v, "text", tmp))
757                PyErr_Clear();
758            Py_DECREF(tmp);
759        }
760    }
761    if (PyObject_SetAttrString(v, "offset", Py_None)) {
762        PyErr_Clear();
763    }
764    if (exc != PyExc_SyntaxError) {
765        if (!PyObject_HasAttrString(v, "msg")) {
766            tmp = PyObject_Str(v);
767            if (tmp) {
768                if (PyObject_SetAttrString(v, "msg", tmp))
769                    PyErr_Clear();
770                Py_DECREF(tmp);
771            } else {
772                PyErr_Clear();
773            }
774        }
775        if (!PyObject_HasAttrString(v, "print_file_and_line")) {
776            if (PyObject_SetAttrString(v, "print_file_and_line",
777                                       Py_None))
778                PyErr_Clear();
779        }
780    }
781    PyErr_Restore(exc, v, tb);
782}
783
784/* com_fetch_program_text will attempt to load the line of text that
785   the exception refers to.  If it fails, it will return NULL but will
786   not set an exception.
787
788   XXX The functionality of this function is quite similar to the
789   functionality in tb_displayline() in traceback.c.
790*/
791
792PyObject *
793PyErr_ProgramText(const char *filename, int lineno)
794{
795    FILE *fp;
796    int i;
797    char linebuf[1000];
798
799    if (filename == NULL || *filename == '\0' || lineno <= 0)
800        return NULL;
801    fp = fopen(filename, "r" PY_STDIOTEXTMODE);
802    if (fp == NULL)
803        return NULL;
804    for (i = 0; i < lineno; i++) {
805        char *pLastChar = &linebuf[sizeof(linebuf) - 2];
806        do {
807            *pLastChar = '\0';
808            if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, fp, NULL) == NULL)
809                break;
810            /* fgets read *something*; if it didn't get as
811               far as pLastChar, it must have found a newline
812               or hit the end of the file; if pLastChar is \n,
813               it obviously found a newline; else we haven't
814               yet seen a newline, so must continue */
815        } while (*pLastChar != '\0' && *pLastChar != '\n');
816    }
817    fclose(fp);
818    if (i == lineno) {
819        char *p = linebuf;
820        while (*p == ' ' || *p == '\t' || *p == '\014')
821            p++;
822        return PyString_FromString(p);
823    }
824    return NULL;
825}
826
827#ifdef __cplusplus
828}
829#endif
830
831