src/atom.c
// -1 for error
// 0 for nontransitive
// 1 for transitive detected (thus class switch needed)
1 for error
0 for nontransitive
1 for transitive detected (thus class switch needed)
1 for error 0 for nontransitive 1 for transitive detected ( thus class switch needed )
static int
parse_use_deps(PyObject *atom_str, char **p_ptr, PyObject **use_ptr, int allow_defaults)
{
	char *p = *p_ptr;
	char *start = p;
	char *use_start, *use_end;
	char transitive_detected = 0;
	Py_ssize_t len = 1;
	PyObject *use = NULL;
	use_start = p;
	for(;;p++) {
		if('\0' == *p) {
			Err_SetMalformedAtom(atom_str,
				"unclosed use dep");
			return -1;
		} else if (',' == *p || ']' == *p) {
			use_end = p - 1;
			if(use_end > use_start) {
				if('-' == *use_start) {
					use_start++;
				} else if('?' == *use_end || '=' == *use_end) {
					use_end--;
					if(use_start != use_end && '!' == *use_start) {
						use_start++;
					}
					transitive_detected = 1;
				}
			}
			if(use_end < use_start) {
				Err_SetMalformedAtom(atom_str,
					"empty use flag detected");
				return -1;
			} else if(!isalnum(*use_start)) {
				Err_SetMalformedAtom(atom_str,
					"first char of a use flag must be alphanumeric");
				return -1;
			}
			if (!allow_defaults) {
				while(use_start <= use_end) {
					if(!VALID_USE_CHAR(*use_start)) {
						Err_SetMalformedAtom(atom_str,
							"invalid char in use dep; each flag must be a-Z0-9_@-+");
						return -1;
					}
					use_start++;
				}
			} else {
				while(use_start <= use_end) {
					if(!VALID_USE_CHAR(*use_start)) {
						if (use_end - use_start == 2 &&
							'(' == use_start[0] &&
								('+' == use_start[1] || '-' == use_start[1]) &&
								')' == use_start[2]) {
							use_start += 3;
							continue;
						}
						Err_SetMalformedAtom(atom_str,
							"invalid char in use dep; each flag must be a-Z0-9_@-+ followed by an optional (+) or (-)");
						return -1;
					}
					use_start++;
				}
			}
			if(']' == *p) {
				break;
			}
			len++;
			use_start = p + 1;
		}
	}
	char *end = p;
	if(len == 1)
		use = PyTuple_New(len);
	else
		use = PyList_New(len);
	if(!use)
		return -1;
	Py_ssize_t idx = 0;
	PyObject *s;
	p = start;
	for(;idx < len;idx++) {
		use_start = p;
		while(',' != *p && ']' != *p)
			p++;
		if(!(s = PyString_FromStringAndSize(use_start, p - use_start))) {
			goto cleanup_use_processing;
		}
		if(len != 1) {
			if(PyList_SetItem(use, idx, s)) {
				Py_DECREF(s);
				goto cleanup_use_processing;
			}
		} else {
			PyTuple_SET_ITEM(use, idx, s);
		}
		p++;
	}
	if(len > 1) {
		if(PyList_Sort(use) < 0)
			goto cleanup_use_processing;
		PyObject *t = PyTuple_New(len);
		if(!t)
			goto cleanup_use_processing;
		register PyObject *x;
		for(idx=0; idx < len; idx++) {
			x = PyList_GET_ITEM(use, idx);
			Py_INCREF(x);
			PyTuple_SET_ITEM(t, idx, x);
		}
		Py_DECREF(use);
		use = t;
	}
	*use_ptr = use;
	*p_ptr = end;
	return transitive_detected;
	cleanup_use_processing:
	Py_CLEAR(use);
	return -1;
}
static int parse_use_deps ( PyObject * atom_str , char * * p_ptr , PyObject * * use_ptr , int allow_defaults ) { char * p = * p_ptr ; char * start = p ; char * use_start , * use_end ; char transitive_detected = 0 ; Py_ssize_t len = 1 ; PyObject * use = NULL ; use_start = p ; for ( ; ; p ++ ) { if ( ' \0 ' == * p ) { Err_SetMalformedAtom ( atom_str , " " ) ; return -1 ; } else if ( ' ' == * p || ' ' == * p ) { use_end = p - 1 ; if ( use_end > use_start ) { if ( ' ' == * use_start ) { use_start ++ ; } else if ( ' ' == * use_end || ' ' == * use_end ) { use_end -- ; if ( use_start != use_end && ' ' == * use_start ) { use_start ++ ; } transitive_detected = 1 ; } } if ( use_end < use_start ) { Err_SetMalformedAtom ( atom_str , " " ) ; return -1 ; } else if ( ! isalnum ( * use_start ) ) { Err_SetMalformedAtom ( atom_str , " " ) ; return -1 ; } if ( ! allow_defaults ) { while ( use_start <= use_end ) { if ( ! VALID_USE_CHAR ( * use_start ) ) { Err_SetMalformedAtom ( atom_str , " " ) ; return -1 ; } use_start ++ ; } } else { while ( use_start <= use_end ) { if ( ! VALID_USE_CHAR ( * use_start ) ) { if ( use_end - use_start == 2 && ' ' == use_start [ 0 ] && ( ' ' == use_start [ 1 ] || ' ' == use_start [ 1 ] ) && ' ' == use_start [ 2 ] ) { use_start += 3 ; continue ; } Err_SetMalformedAtom ( atom_str , " " ) ; return -1 ; } use_start ++ ; } } if ( ' ' == * p ) { break ; } len ++ ; use_start = p + 1 ; } } char * end = p ; if ( len == 1 ) use = PyTuple_New ( len ) ; else use = PyList_New ( len ) ; if ( ! use ) return -1 ; Py_ssize_t idx = 0 ; PyObject * s ; p = start ; for ( ; idx < len ; idx ++ ) { use_start = p ; while ( ' ' != * p && ' ' != * p ) p ++ ; if ( ! ( s = PyString_FromStringAndSize ( use_start , p - use_start ) ) ) { goto cleanup_use_processing ; } if ( len != 1 ) { if ( PyList_SetItem ( use , idx , s ) ) { Py_DECREF ( s ) ; goto cleanup_use_processing ; } } else { PyTuple_SET_ITEM ( use , idx , s ) ; } p ++ ; } if ( len > 1 ) { if ( PyList_Sort ( use ) < 0 ) goto cleanup_use_processing ; PyObject * t = PyTuple_New ( len ) ; if ( ! t ) goto cleanup_use_processing ; register PyObject * x ; for ( idx = 0 ; idx < len ; idx ++ ) { x = PyList_GET_ITEM ( use , idx ) ; Py_INCREF ( x ) ; PyTuple_SET_ITEM ( t , idx , x ) ; } Py_DECREF ( use ) ; use = t ; } * use_ptr = use ; * p_ptr = end ; return transitive_detected ; cleanup_use_processing : Py_CLEAR ( use ) ; return -1 ; }
1 for error
0 for nontransitive
1 for transitive detected (thus class switch needed)
1 for error 0 for nontransitive 1 for transitive detected ( thus class switch needed )
// first find the length of tuple we need // we flip p back one for ease of coding; rely on compiler // to optimize it out. // commutative use.  ! leading is allowed // and now we're validated. // steals the ref. // weak, but it's required for the tuple optimization