summaryrefslogtreecommitdiff
path: root/kicad/pro.c
blob: a113ba158ffd9a9029c4a983654da3a896ae3194 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
 * kicad/pro.c - KiCad profile
 *
 * Written 2016 by Werner Almesberger
 * Copyright 2016 by Werner Almesberger
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#include "misc/util.h"
#include "misc/diag.h"
#include "file/file.h"
#include "kicad/ext.h"
#include "kicad/pro.h"


struct pro_ctx {
	enum pro_state {
		pro_idle,
		pro_libs,	// [eeschema/libraries]
		pro_editor,	// [schematic_editor]
	} state;
	struct file_names *fn;
};


static bool pro_parse_line(const struct file *file,
    void *user, const char *line)
{
	struct pro_ctx *pro = user;
	char *s;

	if (strbegins(line, "[eeschema/libraries]")) {
		pro->state = pro_libs;
		return 1;
	}
	if (strbegins(line, "[schematic_editor]")) {
		pro->state = pro_editor;
		return 1;
	}
	if (*line == '[') {
		pro->state = pro_idle;
		return 1;
	}

	switch (pro->state) {
	case pro_idle:
		break;
	case pro_libs:
		if (sscanf(line, "LibName%*u=%ms", &s) == 1) {
			char *dot;

			pro->fn->n_libs++;
			pro->fn->libs = realloc_type_n(pro->fn->libs,
			    const char *, pro->fn->n_libs);
			dot = strrchr(s, '.');
			if (!dot || strcmp(dot, ".lib")) {
				s = realloc_size(s, strlen(s) + 5);
				strcat(s, ".lib");
			}
			pro->fn->libs[pro->fn->n_libs - 1] = s;
			return 1;
		}
		break;
	case pro_editor:
		if (sscanf(line, "PageLayoutDescrFile=%ms", &s) == 1) {
			free((void *) pro->fn->pl);
			pro->fn->pl = s;
			return 1;
		}
		break;
	default:
		BUG("invalid state %d", pro->state);
	}
	return 1;
}


struct file_names *pro_parse_file(struct file *file,
    const struct file_names *fn_default)
{
	struct pro_ctx pro = {
		.state	= pro_idle,
		.fn	= clone_file_names(fn_default),
	};

	if (!file_read(file, pro_parse_line, &pro)) {
		free_file_names(pro.fn);
		free(pro.fn);
		return NULL;
	}

	if (!pro.fn->sch) {
		char *s, *dot;

		assert(pro.fn->pro);
		s = stralloc(pro.fn->pro);
		dot = strrchr(s, '.');
		assert(!strcmp(dot, ".pro"));
		strcpy(dot, ".sch");
		pro.fn->sch = s;
	}
	return pro.fn;
}