xref: /illumos-gate/usr/src/cmd/adbgen/common/adbsub.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 #pragma ident	"%Z%%M%	%I%	%E% SMI"
23 
24 /*
25  * Copyright (c) 1983-1998 by Sun Microsystems, Inc.
26  * All rights reserved.
27  */
28 
29 /*
30  * Subroutines to be called by adbgen2.c, the C program generated
31  * by adbgen1.c.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 
38 off_t last_off;
39 int warnings = 1;
40 int warns = 0;
41 
42 /*
43  * User claims offset is ok.
44  * This usually follows call to another script, which we cannot handle.
45  */
46 void
47 offsetok(void)
48 {
49 	last_off = -1;
50 }
51 
52 /*
53  * Get adb.s dot to the right offset.
54  */
55 void
56 offset(off_t off)
57 {
58 	off_t off_diff;
59 
60 	if (last_off == -1) {
61 		last_off = off;
62 		return;
63 	}
64 	off_diff = off - last_off;
65 	if (off_diff) {
66 		if (off_diff > 0) {
67 			if (off_diff > 1) {
68 				printf("%ld", off_diff);
69 			}
70 			printf("+");
71 		}
72 		if (off_diff < 0) {
73 			if (off_diff < -1) {
74 				printf("%ld", -off_diff);
75 			}
76 			printf("-");
77 		}
78 	}
79 	last_off = off;
80 }
81 
82 /*
83  * Emit the format command, return the size.
84  */
85 int
86 do_fmt(char *acp)
87 {
88 	int rcount, width, sum, i;
89 	char *cp;
90 
91 	cp = acp;
92 	sum = rcount = 0;
93 	do {
94 		while (*cp >= '0' && *cp <= '9') {
95 			rcount = rcount * 10 + *cp++ - '0';
96 		}
97 		if (rcount == 0) {
98 			rcount = 1;
99 		}
100 		switch (*cp) {
101 		case 'e':
102 		case 'E':
103 		case 'F':
104 		case 'g':
105 		case 'G':
106 		case 'J':
107 			width = 8;
108 			break;
109 		case 'K':
110 #ifdef	_LP64
111 			width = 8;
112 #else	/* _LP64 */
113 			width = 4;
114 #endif	/* _LP64 */
115 			break;
116 		case 'X':
117 		case 'O':
118 		case 'Q':
119 		case 'D':
120 		case 'U':
121 		case 'f':
122 		case 'Y':
123 		case 'p':
124 		case 'P':
125 			width = 4;
126 			break;
127 		case 'x':
128 		case 'o':
129 		case 'q':
130 		case 'd':
131 		case 'u':
132 			width = 2;
133 			break;
134 		case 'v':
135 		case 'V':
136 		case 'b':
137 		case 'B':
138 		case 'c':
139 		case 'C':
140 		case '+':
141 			width = 1;
142 			break;
143 		case 'I':
144 		case 'a':
145 		case 'A':
146 		case 't':
147 		case 'r':
148 		case 'n':
149 			width = 0;
150 			break;
151 		case '-':
152 			width = -1;
153 			break;
154 		case 's':
155 		case 'S':
156 		case 'i':
157 			if (warnings) {
158 				fprintf(stderr,
159 				"Unknown format size \"%s\", assuming zero\n",
160 				acp);
161 				warns++;
162 			}
163 			width = 0;
164 			break;
165 		default:
166 			fprintf(stderr, "Unknown format size: %s\n", acp);
167 			exit(1);
168 		}
169 		for (i = 0; i < rcount; i++) {
170 			putchar(*cp);
171 		}
172 		cp++;
173 		sum += width * rcount;
174 	} while (*cp);
175 	return (sum);
176 }
177 
178 /*
179  * Format struct member, checking size.
180  */
181 void
182 format(char *name, size_t size, char *fmt)
183 {
184 	int fs;
185 
186 	fs = do_fmt(fmt);
187 	if (fs != size && warnings) {
188 		fprintf(stderr,
189 			"warning: \"%s\" size is %ld, \"%s\" width is %d\n",
190 			name, size, fmt, fs);
191 		warns++;
192 	}
193 	last_off += fs;
194 }
195 
196 /*
197  * Get the value at offset based on base.
198  */
199 void
200 indirect(off_t offset, size_t size, char *base, char *member)
201 {
202 	if (size == 8 || size == 4) {
203 		if (offset == 0) {
204 			printf("*%s", base);
205 		} else {
206 			printf("*(%s+0t%ld)", base, offset);
207 		}
208 	} else if (size == 2) {
209 		if (offset == 2) {
210 			printf("(*%s&0xffff)", base);
211 		} else {
212 			printf("(*(%s+0t%ld)&0xffff)", base, offset - 2);
213 		}
214 	} else if (size == 1) {
215 		if (offset == 3) {
216 			printf("(*%s&0xff)", base);
217 		} else {
218 			if ((offset & 0x1) == 0x1) {
219 				printf("(*(%s+0t%ld)&0xff)", base, offset - 3);
220 			} else {
221 				printf("((*(%s+0t%ld)&0xff00)/0x100)",
222 				    base, offset - 2);
223 			}
224 		}
225 	} else {
226 		fprintf(stderr, "Indirect size %ld not 1, 2, or 4: %s\n",
227 		    size, member);
228 		exit(1);
229 	}
230 }
231