view ueda/mclutils/mkbom.c @ 81:6e43956e740d

beginning of BOM utils refactoring: seqrefdes code factored out
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 23 Feb 2017 19:15:48 +0000
parents df98a82b807e
children 20c6f84c75e7
line wrap: on
line source

/*
 * This program generates a procurement-oriented BOM from the MCL.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "../libueda/mcl.h"

extern char *MCLfile;
extern struct component components[];
extern int ncomponents;
extern char *get_comp_attr(), *get_comp_multiattr();
extern struct component *find_partdef_by_name();

struct refdeslist {
	char	*first;
	char	*last;
	struct	refdeslist *next;
};

struct bompart {
	struct	component *part;
	int	qty;
	struct	bompart *next;
	struct	refdeslist *refdeslist;
};

int check_completeness, refdes_lists;
struct bompart *bomhead;

do_cmdline_opts(argc, argv)
	char **argv;
{
	register int c;

	while ((c = getopt(argc, argv, "cM:p:r")) != EOF)
		switch (c) {
		case 'c':
			check_completeness++;
			break;
		case 'M':
			MCLfile = optarg;
			break;
		case 'p':
			set_popopt_list(optarg);
			break;
		case 'r':
			refdes_lists++;
			break;
		default:
			/* getopt prints the error message */
			exit(1);
		}
}

main(argc, argv)
	char **argv;
{
	do_cmdline_opts(argc, argv);
	read_MCL();
	tally_parts();
	output();
	exit(0);
}

tally_parts()
{
	int c;
	register struct component *comp;
	register char *attr;
	struct component *socket;

	for (comp = components, c = 0; c < ncomponents; comp++, c++) {
		if (!check_component_popopt(comp))
			continue;
		if (comp->partdef == NULL) {
			attr = get_comp_attr(comp, "part");
			if (attr && !strcmp(attr, "none"))
				continue;
			if (check_completeness)
				fprintf(stderr, "%s has no part defined\n",
					comp->name);
			continue;
		}
		add_part_to_bom(comp->partdef, comp->name);
		attr = get_comp_attr(comp, "socket");
		if (attr) {
			socket = find_partdef_by_name(attr);
			if (socket)
				add_part_to_bom(socket, comp->name);
			else
				fprintf(stderr,
					"%s: socket part %s not found\n",
					comp->name, attr);
		}
	}
}

add_part_to_bom(part, refdes)
	struct component *part;
	char *refdes;
{
	register struct bompart *bp, **bpp;

	for (bpp = &bomhead; bp = *bpp; bpp = &bp->next)
		if (bp->part == part) {
			bp->qty++;
			add_refdes_to_bompart(bp, refdes);
			return;
		}
	/* new part */
	bp = (struct bompart *) malloc(sizeof(struct bompart));
	if (bp == NULL) {
		perror("malloc");
		exit(1);
	}
	bp->part = part;
	bp->qty = 1;
	bp->next = NULL;
	bp->refdeslist = NULL;
	*bpp = bp;
	add_refdes_to_bompart(bp, refdes);
}

add_refdes_to_bompart(bp, refdes)
	struct bompart *bp;
	char *refdes;
{
	register struct refdeslist *le, **lep;

	if (!refdes_lists)
		return;
	if (!bp->refdeslist) {
		lep = &bp->refdeslist;
		goto add_new;
	}
	for (le = bp->refdeslist; le->next; le = le->next)
		;
	if (is_refdes_sequential(le->last, refdes)) {
		le->last = refdes;
		return(1);
	}
	lep = &le->next;
add_new:
	le = (struct refdeslist *) malloc(sizeof(struct refdeslist));
	if (!le) {
		perror("malloc");
		exit(1);
	}
	le->first = refdes;
	le->last = refdes;
	le->next = NULL;
	*lep = le;
	return(0);
}

output()
{
	register int i;
	register struct component *part;
	register struct bompart *bp;
	char *manuf, *partno, *desc, *spectitle;

	printf("Part\t\t\t\t\t\t\t\t\t    Qty\n");
	for (i = 0; i < 79; i++)
		putchar('-');
	putchar('\n');

	for (bp = bomhead; bp; bp = bp->next) {
		part = bp->part;
		manuf = get_comp_attr(part, "manufacturer");
		partno = get_comp_attr(part, "manufacturer_part_number");
		if (!partno)
			partno = get_comp_attr(part, "device");
		desc = get_comp_attr(part, "description");
		spectitle = get_comp_attr(part, "bom_part_title");
		if (spectitle) {
			fputs(spectitle, stdout);
			i = strlen(spectitle);
		} else if (manuf && partno)
			i = printf("%s %s", manuf, partno);
		else if (desc) {
			fputs(desc, stdout);
			i = strlen(desc);
			desc = NULL;		/* used it */
		} else {
			fprintf(stderr,
			"part %s: no identifying information for the BOM\n",
				part->name);
			continue;
		}
		for (i /= 8; i < 9; i++)
			putchar('\t');
		printf("%7d\n", bp->qty);
		if (desc)
			printf("  %s\n", desc);
		do_comments(part);
		do_sources(part);
		do_substitutes(part);
		if (refdes_lists)
			dump_refdes_list(bp->refdeslist);
	}
}

do_sources(part)
	register struct component *part;
{
	int scnt;
	register char *src;
	char *vendor, *vpn;

	for (scnt = 0; src = get_comp_multiattr(part, "source", &scnt); )
		printf("  Source: %s\n", src);
	if (scnt)
		return;
	/* no source= attributes, check for the old style vendor ones */
	vendor = get_comp_attr(part, "vendor");
	vpn = get_comp_attr(part, "vendor_part_number");
	if (vendor && vpn)
		printf("  Source: %s %s\n", vendor, vpn);
	else if (vendor)
		printf("  Source: %s\n", vendor);
}

do_substitutes(part)
	register struct component *part;
{
	int scnt;
	register char *s;

	for (scnt = 0; s = get_comp_multiattr(part, "substitute", &scnt); )
		printf("  Acceptable substitute: %s\n", s);
}

do_comments(part)
	register struct component *part;
{
	int scnt;
	register char *s;

	for (scnt = 0; s = get_comp_multiattr(part, "bom_comment", &scnt); )
		printf("  %s\n", s);
}

dump_refdes_list(le)
	register struct refdeslist *le;
{
	register int acc, i;

	for (acc = 0; le; le = le->next) {
		i = strlen(le->first) + 1;
		if (le->last != le->first)
			i += strlen(le->last) + 1;
		if (le->next)
			i++;
		if (acc && (acc + i >= 80)) {
			putchar('\n');
			acc = 0;
		}
		if (!acc) {
			putchar(' ');
			acc++;
		}
		printf(" %s", le->first);
		if (le->last != le->first)
			printf("-%s", le->last);
		if (le->next)
			putchar(',');
		acc += i;
	}
	if (acc)
		putchar('\n');
}