Spaces:
No application file
No application file
/* Copyright 2005 by Frank Kauff. All rights reserved. | |
* | |
* This file is part of the Biopython distribution and governed by your | |
* choice of the "Biopython License Agreement" or the "BSD 3-Clause License". | |
* Please see the LICENSE file that should have been included as part of this | |
* package. | |
* | |
* cnexus.c | |
* | |
* Parse input strings, cut out (nested) comments, deal with quoted text. | |
* Input lines terminated with ; are separated by ASCII code 7 (something | |
* that naturally doesn't occur in plain NEXUS files). | |
* | |
* Used by Nexus.py | |
*/ | |
static PyObject * cnexus_scanfile(PyObject *self, PyObject *args) | |
{ | |
PyObject *cleaninput; | |
const char *input; | |
char *scanned, *scanned_start; | |
char t, quotelevel; | |
int speciallevel, commlevel; | |
quotelevel=0; | |
speciallevel=0; | |
commlevel=0; | |
if (!PyArg_ParseTuple(args, "s", &input)) | |
return NULL; | |
if (!(scanned=PyMem_RawMalloc(strlen(input)+1))) | |
PyErr_NoMemory(); | |
scanned_start=scanned; | |
for(t=*input;(t=*input);input++) | |
{ | |
/* end of standard quote */ | |
if (!(commlevel || speciallevel) && t==quotelevel) | |
quotelevel=0; | |
/* start of standard quote */ | |
else if (!quotelevel && !(commlevel || speciallevel) && (t=='\'' || t=='"')) | |
quotelevel=t; | |
/* start of comment outside quote */ | |
else if (!quotelevel && t=='[') | |
{ | |
/* check for special comments */ | |
/*if ((*(input+1)=='!' || *(input+1)=='&' || *(input+1)=='%' || | |
*(input+1)=='/' || *(input+1)=='\\' || *(input+1)=='@') | |
&& !(commlevel || speciallevel)) | |
speciallevel=1; | |
*/ | |
if ((*(input+1)=='&') && !(commlevel || speciallevel)) | |
speciallevel=1; | |
else /* standard comment */ | |
commlevel++; | |
} | |
else if (!quotelevel && t==']') | |
{ | |
/* does it end a special comment? */ | |
if (speciallevel) | |
speciallevel=0; | |
else | |
{ | |
commlevel--; | |
if (commlevel<0) /* error: unmatched ] */ | |
{ | |
PyMem_RawFree(scanned_start); | |
return Py_BuildValue("s","]"); | |
} | |
continue; | |
} | |
} | |
if (!commlevel) | |
{ | |
/* we replace the ; at the end of command lines with special | |
* character to make subsequent parsing of blocks easier */ | |
if (t==';' && !(quotelevel || speciallevel)) | |
/* need an ascii code that's not part of a nexus file, used as | |
* separator */ | |
*(scanned++)=7; | |
else | |
*(scanned++)=t; | |
} | |
/* printf("t %c, commlevel %d, speciallevel %d, quotelevel '%c', scanned %d\n", | |
* t,commlevel,speciallevel,quotelevel,scanned); | |
*/ | |
} | |
if (commlevel>0) | |
{ | |
/* error: unmatched [ */ | |
PyMem_RawFree(scanned_start); | |
return Py_BuildValue("s","["); | |
} | |
else | |
{ | |
*scanned=0; /* end of string */ | |
cleaninput= Py_BuildValue("s",scanned_start); | |
PyMem_RawFree(scanned_start); | |
return cleaninput; | |
} | |
} | |
static PyMethodDef cNexusMethods[]= | |
{ | |
{"scanfile",cnexus_scanfile,METH_VARARGS,"Scan file and deal with comments and quotes."}, | |
{NULL,NULL,0,NULL} | |
}; | |
static struct PyModuleDef moduledef = { | |
PyModuleDef_HEAD_INIT, | |
"cnexus", | |
NULL, | |
-1, | |
cNexusMethods, | |
NULL, | |
NULL, | |
NULL, | |
NULL | |
}; | |
PyObject * | |
PyInit_cnexus(void) | |
{ | |
return PyModule_Create(&moduledef); | |
} | |