]> jfr.im git - irc/quakenet/newserv.git/blob - chanserv/q9snprintf.c
Increased chanlev limit to 500.
[irc/quakenet/newserv.git] / chanserv / q9snprintf.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include "../lib/sstring.h"
6 #include "../core/error.h"
7
8 #define MAXARGS 10
9 #define CONVBUF 512
10
11 struct bufs {
12 char *buf;
13 int capacity;
14 int len;
15 };
16
17 static int addchar(struct bufs *buf, char c) {
18 if(buf->len >= buf->capacity - 1)
19 return 0;
20
21 buf->buf[buf->len++] = c;
22
23 return 1;
24 }
25
26 static int addstr(struct bufs *buf, char *c) {
27 int remaining = buf->capacity - buf->len - 1;
28 char *p;
29
30 for(p=c;*p;p++) {
31 if(remaining-- <= 0)
32 return 0;
33
34 buf->buf[buf->len++] = *p;
35 }
36
37 return 1;
38 }
39
40 void q9vsnprintf(char *buf, size_t size, const char *format, const char *args, va_list ap) {
41 struct bufs b;
42 const char *p;
43 char *c;
44 char convbuf[MAXARGS][CONVBUF];
45
46 if(size == 0)
47 return;
48
49 {
50 int argno = 0, i;
51
52 int d;
53 char *s;
54 double g;
55 unsigned int u;
56
57 for(i=0;i<MAXARGS;i++)
58 convbuf[i][0] = '\0';
59
60 for(;*args;args++) {
61 char *cb = convbuf[argno++];
62
63 switch(*args) {
64 case 's':
65 s = va_arg(ap, char *);
66 snprintf(cb, CONVBUF, "%s", s);
67 break;
68 case 'd':
69 d = va_arg(ap, int);
70 snprintf(cb, CONVBUF, "%d", d);
71 break;
72 case 'u':
73 u = va_arg(ap, unsigned int);
74 snprintf(cb, CONVBUF, "%u", u);
75 break;
76 case 'g':
77 g = va_arg(ap, double);
78 snprintf(cb, CONVBUF, "%.1f", g);
79 break;
80 default:
81 /* calls exit(0) */
82 Error("chanserv", ERR_STOP, "Bad format specifier '%c' supplied in q9vsnprintf, format: '%s'", *args, format);
83 }
84 }
85 }
86
87 b.buf = buf;
88 b.capacity = size;
89 b.len = 0;
90
91 for(p=format;*p;p++) {
92 if(*p != '$') {
93 if(!addchar(&b, *p))
94 break;
95 continue;
96 }
97 p++;
98 if(*p == '\0')
99 break;
100 if(*p == '$') {
101 if(!addchar(&b, *p))
102 break;
103 continue;
104 }
105
106 c = NULL;
107 switch(*p) {
108 /*
109 case 'C':
110 c = botname; break;
111 case 'N':
112 c = network; break;
113 */
114 case '0':
115 case '1':
116 case '2':
117 case '3':
118 case '4':
119 case '5':
120 case '6':
121 case '7':
122 case '8':
123 case '9':
124 c = convbuf[*p - '0']; break;
125 default:
126 c = "(bad format specifier)";
127 }
128 if(c)
129 if(!addstr(&b, c))
130 break;
131 }
132
133 buf[b.len] = '\0';
134
135 /* not required */
136 /*
137 buf[size-1] = '\0';
138 */
139 }
140
141 void q9snprintf(char *buf, size_t size, const char *format, const char *args, ...) {
142 va_list ap;
143
144 va_start(ap, args);
145 q9vsnprintf(buf, size, format, args, ap);
146 va_end(ap);
147 }