static int dgap_parsefile()

in drivers/staging/dgap/dgap.c [6342:7015]


static int dgap_parsefile(char **in)
{
	struct cnode *p, *brd, *line, *conc;
	int rc;
	char *s;
	int linecnt = 0;

	p = &dgap_head;
	brd = line = conc = NULL;

	/* perhaps we are adding to an existing list? */
	while (p->next)
		p = p->next;

	/* file must start with a BEGIN */
	while ((rc = dgap_gettok(in)) != BEGIN) {
		if (rc == 0) {
			pr_err("unexpected EOF");
			return -1;
		}
	}

	for (; ;) {
		int board_type = 0;
		int conc_type = 0;
		int module_type = 0;

		rc = dgap_gettok(in);
		if (rc == 0) {
			pr_err("unexpected EOF");
			return -1;
		}

		switch (rc) {
		case BEGIN:	/* should only be 1 begin */
			pr_err("unexpected config_begin\n");
			return -1;

		case END:
			return 0;

		case BOARD:	/* board info */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;

			p->type = BNODE;
			p->u.board.status = kstrdup("No", GFP_KERNEL);
			line = conc = NULL;
			brd = p;
			linecnt = -1;

			board_type = dgap_gettok(in);
			if (board_type == 0) {
				pr_err("board !!type not specified");
				return -1;
			}

			p->u.board.type = board_type;

			break;

		case IO:	/* i/o port */
			if (p->type != BNODE) {
				pr_err("IO port only vaild for boards");
				return -1;
			}
			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			p->u.board.portstr = kstrdup(s, GFP_KERNEL);
			if (kstrtol(s, 0, &p->u.board.port)) {
				pr_err("bad number for IO port");
				return -1;
			}
			p->u.board.v_port = 1;
			break;

		case MEM:	/* memory address */
			if (p->type != BNODE) {
				pr_err("memory address only vaild for boards");
				return -1;
			}
			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			p->u.board.addrstr = kstrdup(s, GFP_KERNEL);
			if (kstrtoul(s, 0, &p->u.board.addr)) {
				pr_err("bad number for memory address");
				return -1;
			}
			p->u.board.v_addr = 1;
			break;

		case PCIINFO:	/* pci information */
			if (p->type != BNODE) {
				pr_err("memory address only vaild for boards");
				return -1;
			}
			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			p->u.board.pcibusstr = kstrdup(s, GFP_KERNEL);
			if (kstrtoul(s, 0, &p->u.board.pcibus)) {
				pr_err("bad number for pci bus");
				return -1;
			}
			p->u.board.v_pcibus = 1;
			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			p->u.board.pcislotstr = kstrdup(s, GFP_KERNEL);
			if (kstrtoul(s, 0, &p->u.board.pcislot)) {
				pr_err("bad number for pci slot");
				return -1;
			}
			p->u.board.v_pcislot = 1;
			break;

		case METHOD:
			if (p->type != BNODE) {
				pr_err("install method only vaild for boards");
				return -1;
			}
			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			p->u.board.method = kstrdup(s, GFP_KERNEL);
			p->u.board.v_method = 1;
			break;

		case STATUS:
			if (p->type != BNODE) {
				pr_err("config status only vaild for boards");
				return -1;
			}
			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			p->u.board.status = kstrdup(s, GFP_KERNEL);
			break;

		case NPORTS:	/* number of ports */
			if (p->type == BNODE) {
				s = dgap_getword(in);
				if (!s) {
					pr_err("unexpected end of file");
					return -1;
				}
				if (kstrtol(s, 0, &p->u.board.nport)) {
					pr_err("bad number for number of ports");
					return -1;
				}
				p->u.board.v_nport = 1;
			} else if (p->type == CNODE) {
				s = dgap_getword(in);
				if (!s) {
					pr_err("unexpected end of file");
					return -1;
				}
				if (kstrtol(s, 0, &p->u.conc.nport)) {
					pr_err("bad number for number of ports");
					return -1;
				}
				p->u.conc.v_nport = 1;
			} else if (p->type == MNODE) {
				s = dgap_getword(in);
				if (!s) {
					pr_err("unexpected end of file");
					return -1;
				}
				if (kstrtol(s, 0, &p->u.module.nport)) {
					pr_err("bad number for number of ports");
					return -1;
				}
				p->u.module.v_nport = 1;
			} else {
				pr_err("nports only valid for concentrators or modules");
				return -1;
			}
			break;

		case ID:	/* letter ID used in tty name */
			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}

			p->u.board.status = kstrdup(s, GFP_KERNEL);

			if (p->type == CNODE) {
				p->u.conc.id = kstrdup(s, GFP_KERNEL);
				p->u.conc.v_id = 1;
			} else if (p->type == MNODE) {
				p->u.module.id = kstrdup(s, GFP_KERNEL);
				p->u.module.v_id = 1;
			} else {
				pr_err("id only valid for concentrators or modules");
				return -1;
			}
			break;

		case STARTO:	/* start offset of ID */
			if (p->type == BNODE) {
				s = dgap_getword(in);
				if (!s) {
					pr_err("unexpected end of file");
					return -1;
				}
				if (kstrtol(s, 0, &p->u.board.start)) {
					pr_err("bad number for start of tty count");
					return -1;
				}
				p->u.board.v_start = 1;
			} else if (p->type == CNODE) {
				s = dgap_getword(in);
				if (!s) {
					pr_err("unexpected end of file");
					return -1;
				}
				if (kstrtol(s, 0, &p->u.conc.start)) {
					pr_err("bad number for start of tty count");
					return -1;
				}
				p->u.conc.v_start = 1;
			} else if (p->type == MNODE) {
				s = dgap_getword(in);
				if (!s) {
					pr_err("unexpected end of file");
					return -1;
				}
				if (kstrtol(s, 0, &p->u.module.start)) {
					pr_err("bad number for start of tty count");
					return -1;
				}
				p->u.module.v_start = 1;
			} else {
				pr_err("start only valid for concentrators or modules");
				return -1;
			}
			break;

		case TTYN:	/* tty name prefix */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = TNODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpeced end of file");
				return -1;
			}
			p->u.ttyname = kstrdup(s, GFP_KERNEL);
			if (!p->u.ttyname)
				return -1;

			break;

		case CU:	/* cu name prefix */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = CUNODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpeced end of file");
				return -1;
			}
			p->u.cuname = kstrdup(s, GFP_KERNEL);
			if (!p->u.cuname)
				return -1;

			break;

		case LINE:	/* line information */
			if (dgap_checknode(p))
				return -1;
			if (!brd) {
				pr_err("must specify board before line info");
				return -1;
			}
			switch (brd->u.board.type) {
			case PPCM:
				pr_err("line not vaild for PC/em");
				return -1;
			}

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = LNODE;
			conc = NULL;
			line = p;
			linecnt++;
			break;

		case CONC:	/* concentrator information */
			if (dgap_checknode(p))
				return -1;
			if (!line) {
				pr_err("must specify line info before concentrator");
				return -1;
			}

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = CNODE;
			conc = p;

			if (linecnt)
				brd->u.board.conc2++;
			else
				brd->u.board.conc1++;

			conc_type = dgap_gettok(in);
			if (conc_type == 0 || conc_type != CX ||
			    conc_type != EPC) {
				pr_err("failed to set a type of concentratros");
				return -1;
			}

			p->u.conc.type = conc_type;

			break;

		case MOD:	/* EBI module */
			if (dgap_checknode(p))
				return -1;
			if (!brd) {
				pr_err("must specify board info before EBI modules");
				return -1;
			}
			switch (brd->u.board.type) {
			case PPCM:
				linecnt = 0;
				break;
			default:
				if (!conc) {
					pr_err("must specify concentrator info before EBI module");
					return -1;
				}
			}

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = MNODE;

			if (linecnt)
				brd->u.board.module2++;
			else
				brd->u.board.module1++;

			module_type = dgap_gettok(in);
			if (module_type == 0 || module_type != PORTS ||
			    module_type != MODEM) {
				pr_err("failed to set a type of module");
				return -1;
			}

			p->u.module.type = module_type;

			break;

		case CABLE:
			if (p->type == LNODE) {
				s = dgap_getword(in);
				if (!s) {
					pr_err("unexpected end of file");
					return -1;
				}
				p->u.line.cable = kstrdup(s, GFP_KERNEL);
				p->u.line.v_cable = 1;
			}
			break;

		case SPEED:	/* sync line speed indication */
			if (p->type == LNODE) {
				s = dgap_getword(in);
				if (!s) {
					pr_err("unexpected end of file");
					return -1;
				}
				if (kstrtol(s, 0, &p->u.line.speed)) {
					pr_err("bad number for line speed");
					return -1;
				}
				p->u.line.v_speed = 1;
			} else if (p->type == CNODE) {
				s = dgap_getword(in);
				if (!s) {
					pr_err("unexpected end of file");
					return -1;
				}
				if (kstrtol(s, 0, &p->u.conc.speed)) {
					pr_err("bad number for line speed");
					return -1;
				}
				p->u.conc.v_speed = 1;
			} else {
				pr_err("speed valid only for lines or concentrators.");
				return -1;
			}
			break;

		case CONNECT:
			if (p->type == CNODE) {
				s = dgap_getword(in);
				if (!s) {
					pr_err("unexpected end of file");
					return -1;
				}
				p->u.conc.connect = kstrdup(s, GFP_KERNEL);
				p->u.conc.v_connect = 1;
			}
			break;
		case PRINT:	/* transparent print name prefix */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = PNODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpeced end of file");
				return -1;
			}
			p->u.printname = kstrdup(s, GFP_KERNEL);
			if (!p->u.printname)
				return -1;

			break;

		case CMAJOR:	/* major number */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = JNODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			if (kstrtol(s, 0, &p->u.majornumber)) {
				pr_err("bad number for major number");
				return -1;
			}
			break;

		case ALTPIN:	/* altpin setting */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = ANODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			if (kstrtol(s, 0, &p->u.altpin)) {
				pr_err("bad number for altpin");
				return -1;
			}
			break;

		case USEINTR:		/* enable interrupt setting */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = INTRNODE;
			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			if (kstrtol(s, 0, &p->u.useintr)) {
				pr_err("bad number for useintr");
				return -1;
			}
			break;

		case TTSIZ:	/* size of tty structure */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = TSNODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			if (kstrtol(s, 0, &p->u.ttysize)) {
				pr_err("bad number for ttysize");
				return -1;
			}
			break;

		case CHSIZ:	/* channel structure size */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = CSNODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			if (kstrtol(s, 0, &p->u.chsize)) {
				pr_err("bad number for chsize");
				return -1;
			}
			break;

		case BSSIZ:	/* board structure size */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = BSNODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			if (kstrtol(s, 0, &p->u.bssize)) {
				pr_err("bad number for bssize");
				return -1;
			}
			break;

		case UNTSIZ:	/* sched structure size */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = USNODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			if (kstrtol(s, 0, &p->u.unsize)) {
				pr_err("bad number for schedsize");
				return -1;
			}
			break;

		case F2SIZ:	/* f2200 structure size */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = FSNODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			if (kstrtol(s, 0, &p->u.f2size)) {
				pr_err("bad number for f2200size");
				return -1;
			}
			break;

		case VPSIZ:	/* vpix structure size */
			if (dgap_checknode(p))
				return -1;

			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
			if (!p->next)
				return -1;

			p = p->next;
			p->type = VSNODE;

			s = dgap_getword(in);
			if (!s) {
				pr_err("unexpected end of file");
				return -1;
			}
			if (kstrtol(s, 0, &p->u.vpixsize)) {
				pr_err("bad number for vpixsize");
				return -1;
			}
			break;
		}
	}
}