runtime.c 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832
  1. /*
  2. runtime.c -- Runtime support
  3. Copyright (c) All Rights Reserved. See details at the end of the file.
  4. */
  5. /*********************************** Includes *********************************/
  6. #include "goahead.h"
  7. /*********************************** Defines **********************************/
  8. /*
  9. This structure stores scheduled events.
  10. */
  11. typedef struct Callback {
  12. void (*routine)(void *arg, int id);
  13. void *arg;
  14. WebsTime at;
  15. int id;
  16. } Callback;
  17. /*********************************** Defines **********************************/
  18. /*
  19. Class definitions
  20. */
  21. #define CLASS_NORMAL 0 /* [All other] Normal characters */
  22. #define CLASS_PERCENT 1 /* [%] Begin format */
  23. #define CLASS_MODIFIER 2 /* [-+ #,] Modifiers */
  24. #define CLASS_ZERO 3 /* [0] Special modifier - zero pad */
  25. #define CLASS_STAR 4 /* [*] Width supplied by arg */
  26. #define CLASS_DIGIT 5 /* [1-9] Field widths */
  27. #define CLASS_DOT 6 /* [.] Introduce precision */
  28. #define CLASS_BITS 7 /* [hlL] Length bits */
  29. #define CLASS_TYPE 8 /* [cdefginopsSuxX] Type specifiers */
  30. #define STATE_NORMAL 0 /* Normal chars in format string */
  31. #define STATE_PERCENT 1 /* "%" */
  32. #define STATE_MODIFIER 2 /* -+ #,*/
  33. #define STATE_WIDTH 3 /* Width spec */
  34. #define STATE_DOT 4 /* "." */
  35. #define STATE_PRECISION 5 /* Precision spec */
  36. #define STATE_BITS 6 /* Size spec */
  37. #define STATE_TYPE 7 /* Data type */
  38. #define STATE_COUNT 8
  39. PUBLIC char stateMap[] = {
  40. /* STATES: Normal Percent Modifier Width Dot Prec Bits Type */
  41. /* CLASS 0 1 2 3 4 5 6 7 */
  42. /* Normal 0 */ 0, 0, 0, 0, 0, 0, 0, 0,
  43. /* Percent 1 */ 1, 0, 1, 1, 1, 1, 1, 1,
  44. /* Modifier 2 */ 0, 2, 2, 0, 0, 0, 0, 0,
  45. /* Zero 3 */ 0, 2, 2, 3, 5, 5, 0, 0,
  46. /* Star 4 */ 0, 3, 3, 0, 5, 0, 0, 0,
  47. /* Digit 5 */ 0, 3, 3, 3, 5, 5, 0, 0,
  48. /* Dot 6 */ 0, 4, 4, 4, 0, 0, 0, 0,
  49. /* Bits 7 */ 0, 6, 6, 6, 6, 6, 6, 0,
  50. /* Types 8 */ 0, 7, 7, 7, 7, 7, 7, 0,
  51. };
  52. /*
  53. Format: %[modifier][width][precision][bits][type]
  54. The Class map will map from a specifier letter to a state.
  55. */
  56. PUBLIC char classMap[] = {
  57. /* 0 ' ' ! " # $ % & ' */
  58. 2, 0, 0, 2, 0, 1, 0, 0,
  59. /* 07 ( ) * + , - . / */
  60. 0, 0, 4, 2, 2, 2, 6, 0,
  61. /* 10 0 1 2 3 4 5 6 7 */
  62. 3, 5, 5, 5, 5, 5, 5, 5,
  63. /* 17 8 9 : ; < = > ? */
  64. 5, 5, 0, 0, 0, 0, 0, 0,
  65. /* 20 @ A B C D E F G */
  66. 8, 0, 0, 0, 0, 0, 0, 0,
  67. /* 27 H I J K L M N O */
  68. 0, 0, 0, 0, 7, 0, 8, 0,
  69. /* 30 P Q R S T U V W */
  70. 0, 0, 0, 8, 0, 0, 0, 0,
  71. /* 37 X Y Z [ \ ] ^ _ */
  72. 8, 0, 0, 0, 0, 0, 0, 0,
  73. /* 40 ' a b c d e f g */
  74. 0, 0, 0, 8, 8, 8, 8, 8,
  75. /* 47 h i j k l m n o */
  76. 7, 8, 0, 0, 7, 0, 8, 8,
  77. /* 50 p q r s t u v w */
  78. 8, 0, 0, 8, 0, 8, 0, 8,
  79. /* 57 x y z */
  80. 8, 0, 0,
  81. };
  82. /*
  83. Flags
  84. */
  85. #define SPRINTF_LEFT 0x1 /* Left align */
  86. #define SPRINTF_SIGN 0x2 /* Always sign the result */
  87. #define SPRINTF_LEAD_SPACE 0x4 /* put leading space for +ve numbers */
  88. #define SPRINTF_ALTERNATE 0x8 /* Alternate format */
  89. #define SPRINTF_LEAD_ZERO 0x10 /* Zero pad */
  90. #define SPRINTF_SHORT 0x20 /* 16-bit */
  91. #define SPRINTF_LONG 0x40 /* 32-bit */
  92. #define SPRINTF_INT64 0x80 /* 64-bit */
  93. #define SPRINTF_COMMA 0x100 /* Thousand comma separators */
  94. #define SPRINTF_UPPER_CASE 0x200 /* As the name says for numbers */
  95. typedef struct Format {
  96. uchar *buf;
  97. uchar *endbuf;
  98. uchar *start;
  99. uchar *end;
  100. ssize growBy;
  101. ssize maxsize;
  102. int precision;
  103. int radix;
  104. int width;
  105. int flags;
  106. int len;
  107. } Format;
  108. #define BPUT(fmt, c) \
  109. do { \
  110. /* Less one to allow room for the null */ \
  111. if ((fmt)->end >= ((fmt)->endbuf - sizeof(char))) { \
  112. if (growBuf(fmt) > 0) { \
  113. *(fmt)->end++ = (c); \
  114. } \
  115. } else { \
  116. *(fmt)->end++ = (c); \
  117. } \
  118. } while (0)
  119. #define BPUTNULL(fmt) \
  120. do { \
  121. if ((fmt)->end > (fmt)->endbuf) { \
  122. if (growBuf(fmt) > 0) { \
  123. *(fmt)->end = '\0'; \
  124. } \
  125. } else { \
  126. *(fmt)->end = '\0'; \
  127. } \
  128. } while (0)
  129. /*
  130. The handle list stores the length of the list and the number of used handles in the first two words. These are
  131. hidden from the caller by returning a pointer to the third word to the caller.
  132. */
  133. #define H_LEN 0 /* First entry holds length of list */
  134. #define H_USED 1 /* Second entry holds number of used */
  135. #define H_OFFSET 2 /* Offset to real start of list */
  136. #define H_INCR 16 /* Grow handle list in chunks this size */
  137. #define RINGQ_LEN(bp) ((bp->servp > bp->endp) ? (bp->buflen + (bp->endp - bp->servp)) : (bp->endp - bp->servp))
  138. typedef struct HashTable { /* Symbol table descriptor */
  139. WebsKey **hash_table; /* Allocated at run time */
  140. int inuse; /* Is this entry in use */
  141. int size; /* Size of the table below */
  142. } HashTable;
  143. #ifndef LOG_ERR
  144. #define LOG_ERR 0
  145. #endif
  146. #if ME_WIN_LIKE
  147. PUBLIC void syslog(int priority, char *fmt, ...);
  148. #endif
  149. PUBLIC int logLevel; /* Log verbosity level */
  150. /************************************* Locals *********************************/
  151. static Callback **callbacks;
  152. static int callbackMax;
  153. static HashTable **sym; /* List of symbol tables */
  154. static int symMax; /* One past the max symbol table */
  155. char *embedthisGoAheadCopyright = EMBEDTHIS_GOAHEAD_COPYRIGHT;
  156. #if ME_GOAHEAD_LOGGING
  157. static char *logPath; /* Log file name */
  158. static int logFd; /* Log file handle */
  159. #endif
  160. /********************************** Forwards **********************************/
  161. static int calcPrime(int size);
  162. static int getBinBlockSize(int size);
  163. static int hashIndex(HashTable *tp, char *name);
  164. static WebsKey *hash(HashTable *tp, char *name);
  165. #if ME_GOAHEAD_LOGGING
  166. static void defaultLogHandler(int level, char *buf);
  167. static WebsLogHandler logHandler = defaultLogHandler;
  168. #endif
  169. static int getState(char c, int state);
  170. static int growBuf(Format *fmt);
  171. static char *sprintfCore(char *buf, ssize maxsize, char *fmt, va_list arg);
  172. static void outNum(Format *fmt, char *prefix, uint64 val);
  173. static void outString(Format *fmt, char *str, ssize len);
  174. #if ME_FLOAT
  175. static void outFloat(Format *fmt, char specChar, double value);
  176. #endif
  177. /************************************* Code ***********************************/
  178. PUBLIC int websRuntimeOpen()
  179. {
  180. symMax = 0;
  181. sym = 0;
  182. srand((uint) time(NULL));
  183. return 0;
  184. }
  185. PUBLIC void websRuntimeClose()
  186. {
  187. }
  188. /*
  189. This function is called when a scheduled process time has come.
  190. */
  191. static void callEvent(int id)
  192. {
  193. Callback *cp;
  194. assert(0 <= id && id < callbackMax);
  195. cp = callbacks[id];
  196. assert(cp);
  197. (cp->routine)(cp->arg, cp->id);
  198. }
  199. /*
  200. Schedule an event in delay milliseconds time. We will use 1 second granularity for webServer.
  201. */
  202. PUBLIC int websStartEvent(int delay, WebsEventProc proc, void *arg)
  203. {
  204. Callback *s;
  205. int id;
  206. if ((id = wallocObject(&callbacks, &callbackMax, sizeof(Callback))) < 0) {
  207. return -1;
  208. }
  209. s = callbacks[id];
  210. s->routine = proc;
  211. s->arg = arg;
  212. s->id = id;
  213. /*
  214. Round the delay up to seconds.
  215. */
  216. s->at = ((delay + 500) / 1000) + time(0);
  217. return id;
  218. }
  219. PUBLIC void websRestartEvent(int id, int delay)
  220. {
  221. Callback *s;
  222. if (callbacks == NULL || id == -1 || id >= callbackMax || (s = callbacks[id]) == NULL) {
  223. return;
  224. }
  225. s->at = ((delay + 500) / 1000) + time(0);
  226. }
  227. PUBLIC void websStopEvent(int id)
  228. {
  229. Callback *s;
  230. if (callbacks == NULL || id == -1 || id >= callbackMax || (s = callbacks[id]) == NULL) {
  231. return;
  232. }
  233. wfree(s);
  234. callbackMax = wfreeHandle(&callbacks, id);
  235. }
  236. int websRunEvents()
  237. {
  238. Callback *s;
  239. WebsTime now;
  240. int i, delay, nextEvent;
  241. // printf("---> websRunEvents\n");
  242. nextEvent = (MAXINT / 1000);
  243. now = time(0);
  244. for (i = 0; i < callbackMax; i++) {
  245. if ((s = callbacks[i]) != NULL) {
  246. if (s->at <= now) {
  247. callEvent(i);
  248. delay = MAXINT / 1000;
  249. /* Rescan incase event scheduled or modified an event */
  250. i = -1;
  251. } else {
  252. delay = (int) min(s->at - now, MAXINT / 1000);
  253. }
  254. nextEvent = min(delay, nextEvent);
  255. }
  256. }
  257. return nextEvent * 1000;
  258. }
  259. /*
  260. Allocating secure replacement for sprintf and vsprintf.
  261. */
  262. PUBLIC char *sfmt(char *format, ...)
  263. {
  264. va_list ap;
  265. char *result;
  266. assert(format);
  267. va_start(ap, format);
  268. result = sprintfCore(NULL, -1, format, ap);
  269. va_end(ap);
  270. return result;
  271. }
  272. /*
  273. Replacement for sprintf
  274. */
  275. PUBLIC char *fmt(char *buf, ssize bufsize, char *format, ...)
  276. {
  277. va_list ap;
  278. char *result;
  279. assert(buf);
  280. assert(format);
  281. if (bufsize <= 0) {
  282. return 0;
  283. }
  284. va_start(ap, format);
  285. result = sprintfCore(buf, bufsize, format, ap);
  286. va_end(ap);
  287. return result;
  288. }
  289. /*
  290. Scure vsprintf replacement
  291. */
  292. PUBLIC char *sfmtv(char *fmt, va_list arg)
  293. {
  294. assert(fmt);
  295. return sprintfCore(NULL, -1, fmt, arg);
  296. }
  297. static int getState(char c, int state)
  298. {
  299. int chrClass;
  300. if (c < ' ' || c > 'z') {
  301. chrClass = CLASS_NORMAL;
  302. } else {
  303. assert((c - ' ') < (int) sizeof(classMap));
  304. chrClass = classMap[(c - ' ')];
  305. }
  306. assert((chrClass * STATE_COUNT + state) < (int) sizeof(stateMap));
  307. state = stateMap[chrClass * STATE_COUNT + state];
  308. return state;
  309. }
  310. static char *sprintfCore(char *buf, ssize maxsize, char *spec, va_list args)
  311. {
  312. Format fmt;
  313. ssize len;
  314. int64 iValue;
  315. uint64 uValue;
  316. int state;
  317. char c, *safe;
  318. if (spec == 0) {
  319. spec = "";
  320. }
  321. if (buf != 0) {
  322. assert(maxsize > 0);
  323. fmt.buf = (uchar*) buf;
  324. fmt.endbuf = &fmt.buf[maxsize];
  325. fmt.growBy = -1;
  326. } else {
  327. if (maxsize <= 0) {
  328. maxsize = MAXINT;
  329. }
  330. len = min(256, maxsize);
  331. if ((buf = walloc(len)) == 0) {
  332. return 0;
  333. }
  334. fmt.buf = (uchar*) buf;
  335. fmt.endbuf = &fmt.buf[len];
  336. fmt.growBy = min(512, maxsize - len);
  337. }
  338. fmt.maxsize = maxsize;
  339. fmt.start = fmt.buf;
  340. fmt.end = fmt.buf;
  341. fmt.len = 0;
  342. *fmt.start = '\0';
  343. state = STATE_NORMAL;
  344. while ((c = *spec++) != '\0') {
  345. state = getState(c, state);
  346. switch (state) {
  347. case STATE_NORMAL:
  348. BPUT(&fmt, c);
  349. break;
  350. case STATE_PERCENT:
  351. fmt.precision = -1;
  352. fmt.width = 0;
  353. fmt.flags = 0;
  354. break;
  355. case STATE_MODIFIER:
  356. switch (c) {
  357. case '+':
  358. fmt.flags |= SPRINTF_SIGN;
  359. break;
  360. case '-':
  361. fmt.flags |= SPRINTF_LEFT;
  362. break;
  363. case '#':
  364. fmt.flags |= SPRINTF_ALTERNATE;
  365. break;
  366. case '0':
  367. fmt.flags |= SPRINTF_LEAD_ZERO;
  368. break;
  369. case ' ':
  370. fmt.flags |= SPRINTF_LEAD_SPACE;
  371. break;
  372. case ',':
  373. fmt.flags |= SPRINTF_COMMA;
  374. break;
  375. }
  376. break;
  377. case STATE_WIDTH:
  378. if (c == '*') {
  379. fmt.width = va_arg(args, int);
  380. if (fmt.width < 0) {
  381. fmt.width = -fmt.width;
  382. fmt.flags |= SPRINTF_LEFT;
  383. }
  384. } else {
  385. while (isdigit((uchar) c)) {
  386. fmt.width = fmt.width * 10 + (c - '0');
  387. c = *spec++;
  388. }
  389. spec--;
  390. }
  391. break;
  392. case STATE_DOT:
  393. fmt.precision = 0;
  394. break;
  395. case STATE_PRECISION:
  396. if (c == '*') {
  397. fmt.precision = va_arg(args, int);
  398. } else {
  399. while (isdigit((uchar) c)) {
  400. fmt.precision = fmt.precision * 10 + (c - '0');
  401. c = *spec++;
  402. }
  403. spec--;
  404. }
  405. break;
  406. case STATE_BITS:
  407. switch (c) {
  408. case 'L':
  409. fmt.flags |= SPRINTF_INT64;
  410. break;
  411. case 'l':
  412. fmt.flags |= SPRINTF_LONG;
  413. break;
  414. case 'h':
  415. fmt.flags |= SPRINTF_SHORT;
  416. break;
  417. }
  418. break;
  419. case STATE_TYPE:
  420. switch (c) {
  421. case 'e':
  422. #if ME_FLOAT
  423. case 'g':
  424. case 'f':
  425. fmt.radix = 10;
  426. outFloat(&fmt, c, (double) va_arg(args, double));
  427. break;
  428. #endif /* ME_FLOAT */
  429. case 'c':
  430. BPUT(&fmt, (char) va_arg(args, int));
  431. break;
  432. case 'S':
  433. /* Safe string */
  434. #if ME_CHAR_LEN > 1 && KEEP
  435. if (fmt.flags & SPRINTF_LONG) {
  436. // UNICODE - not right wchar
  437. safe = websEscapeHtml(va_arg(args, wchar*));
  438. outWideString(&fmt, safe, -1);
  439. wfree(safe);
  440. } else
  441. #endif
  442. {
  443. safe = websEscapeHtml(va_arg(args, char*));
  444. outString(&fmt, safe, -1);
  445. wfree(safe);
  446. }
  447. break;
  448. case 'w':
  449. /* Wide string of wchar characters (Same as %ls"). Null terminated. */
  450. #if ME_CHAR_LEN > 1 && KEEP
  451. outWideString(&fmt, va_arg(args, wchar*), -1);
  452. break;
  453. #else
  454. /* Fall through */
  455. #endif
  456. case 's':
  457. /* Standard string */
  458. #if ME_CHAR_LEN > 1 && KEEP
  459. if (fmt.flags & SPRINTF_LONG) {
  460. outWideString(&fmt, va_arg(args, wchar*), -1);
  461. } else
  462. #endif
  463. outString(&fmt, va_arg(args, char*), -1);
  464. break;
  465. case 'i':
  466. case 'd':
  467. fmt.radix = 10;
  468. if (fmt.flags & SPRINTF_SHORT) {
  469. iValue = (short) va_arg(args, int);
  470. } else if (fmt.flags & SPRINTF_LONG) {
  471. iValue = (long) va_arg(args, long);
  472. } else if (fmt.flags & SPRINTF_INT64) {
  473. iValue = (int64) va_arg(args, int64);
  474. } else {
  475. iValue = (int) va_arg(args, int);
  476. }
  477. if (iValue >= 0) {
  478. if (fmt.flags & SPRINTF_LEAD_SPACE) {
  479. outNum(&fmt, " ", iValue);
  480. } else if (fmt.flags & SPRINTF_SIGN) {
  481. outNum(&fmt, "+", iValue);
  482. } else {
  483. outNum(&fmt, 0, iValue);
  484. }
  485. } else {
  486. outNum(&fmt, "-", -iValue);
  487. }
  488. break;
  489. case 'X':
  490. fmt.flags |= SPRINTF_UPPER_CASE;
  491. #if ME_64
  492. fmt.flags &= ~(SPRINTF_SHORT|SPRINTF_LONG);
  493. fmt.flags |= SPRINTF_INT64;
  494. #else
  495. fmt.flags &= ~(SPRINTF_INT64);
  496. #endif
  497. /* Fall through */
  498. case 'o':
  499. case 'x':
  500. case 'u':
  501. if (fmt.flags & SPRINTF_SHORT) {
  502. uValue = (ushort) va_arg(args, uint);
  503. } else if (fmt.flags & SPRINTF_LONG) {
  504. uValue = (ulong) va_arg(args, ulong);
  505. } else if (fmt.flags & SPRINTF_INT64) {
  506. uValue = (uint64) va_arg(args, uint64);
  507. } else {
  508. uValue = va_arg(args, uint);
  509. }
  510. if (c == 'u') {
  511. fmt.radix = 10;
  512. outNum(&fmt, 0, uValue);
  513. } else if (c == 'o') {
  514. fmt.radix = 8;
  515. if (fmt.flags & SPRINTF_ALTERNATE && uValue != 0) {
  516. outNum(&fmt, "0", uValue);
  517. } else {
  518. outNum(&fmt, 0, uValue);
  519. }
  520. } else {
  521. fmt.radix = 16;
  522. if (fmt.flags & SPRINTF_ALTERNATE && uValue != 0) {
  523. if (c == 'X') {
  524. outNum(&fmt, "0X", uValue);
  525. } else {
  526. outNum(&fmt, "0x", uValue);
  527. }
  528. } else {
  529. outNum(&fmt, 0, uValue);
  530. }
  531. }
  532. break;
  533. case 'n': /* Count of chars seen thus far */
  534. if (fmt.flags & SPRINTF_SHORT) {
  535. short *count = va_arg(args, short*);
  536. *count = (int) (fmt.end - fmt.start);
  537. } else if (fmt.flags & SPRINTF_LONG) {
  538. long *count = va_arg(args, long*);
  539. *count = (int) (fmt.end - fmt.start);
  540. } else {
  541. int *count = va_arg(args, int *);
  542. *count = (int) (fmt.end - fmt.start);
  543. }
  544. break;
  545. case 'p': /* Pointer */
  546. #if ME_64
  547. uValue = (uint64) va_arg(args, void*);
  548. #else
  549. uValue = (uint) PTOI(va_arg(args, void*));
  550. #endif
  551. fmt.radix = 16;
  552. outNum(&fmt, "0x", uValue);
  553. break;
  554. default:
  555. BPUT(&fmt, c);
  556. }
  557. }
  558. }
  559. BPUTNULL(&fmt);
  560. return (char*) fmt.buf;
  561. }
  562. static void outString(Format *fmt, char *str, ssize len)
  563. {
  564. char *cp;
  565. ssize i;
  566. if (str == NULL) {
  567. str = "null";
  568. len = 4;
  569. } else if (fmt->flags & SPRINTF_ALTERNATE) {
  570. str++;
  571. len = (ssize) *str;
  572. } else if (fmt->precision >= 0) {
  573. for (cp = str, len = 0; len < fmt->precision; len++) {
  574. if (*cp++ == '\0') {
  575. break;
  576. }
  577. }
  578. } else if (len < 0) {
  579. len = slen(str);
  580. }
  581. if (!(fmt->flags & SPRINTF_LEFT)) {
  582. for (i = len; i < fmt->width; i++) {
  583. BPUT(fmt, (char) ' ');
  584. }
  585. }
  586. for (i = 0; i < len && *str; i++) {
  587. BPUT(fmt, *str++);
  588. }
  589. if (fmt->flags & SPRINTF_LEFT) {
  590. for (i = len; i < fmt->width; i++) {
  591. BPUT(fmt, (char) ' ');
  592. }
  593. }
  594. }
  595. #if ME_CHAR_LEN > 1 && KEEP
  596. static void outWideString(Format *fmt, wchar *str, ssize len)
  597. {
  598. wchar *cp;
  599. int i;
  600. if (str == 0) {
  601. BPUT(fmt, (char) 'n');
  602. BPUT(fmt, (char) 'u');
  603. BPUT(fmt, (char) 'l');
  604. BPUT(fmt, (char) 'l');
  605. return;
  606. } else if (fmt->flags & SPRINTF_ALTERNATE) {
  607. str++;
  608. len = (ssize) *str;
  609. } else if (fmt->precision >= 0) {
  610. for (cp = str, len = 0; len < fmt->precision; len++) {
  611. if (*cp++ == 0) {
  612. break;
  613. }
  614. }
  615. } else if (len < 0) {
  616. for (cp = str, len = 0; *cp++ == 0; len++) ;
  617. }
  618. if (!(fmt->flags & SPRINTF_LEFT)) {
  619. for (i = len; i < fmt->width; i++) {
  620. BPUT(fmt, (char) ' ');
  621. }
  622. }
  623. for (i = 0; i < len && *str; i++) {
  624. BPUT(fmt, *str++);
  625. }
  626. if (fmt->flags & SPRINTF_LEFT) {
  627. for (i = len; i < fmt->width; i++) {
  628. BPUT(fmt, (char) ' ');
  629. }
  630. }
  631. }
  632. #endif
  633. static void outNum(Format *fmt, char *prefix, uint64 value)
  634. {
  635. char numBuf[64];
  636. char *cp;
  637. char *endp;
  638. char c;
  639. int letter, len, leadingZeros, i, fill;
  640. endp = &numBuf[sizeof(numBuf) - 1];
  641. *endp = '\0';
  642. cp = endp;
  643. /*
  644. * Convert to ascii
  645. */
  646. if (fmt->radix == 16) {
  647. do {
  648. letter = (int) (value % fmt->radix);
  649. if (letter > 9) {
  650. if (fmt->flags & SPRINTF_UPPER_CASE) {
  651. letter = 'A' + letter - 10;
  652. } else {
  653. letter = 'a' + letter - 10;
  654. }
  655. } else {
  656. letter += '0';
  657. }
  658. *--cp = letter;
  659. value /= fmt->radix;
  660. } while (value > 0);
  661. } else if (fmt->flags & SPRINTF_COMMA) {
  662. i = 1;
  663. do {
  664. *--cp = '0' + (int) (value % fmt->radix);
  665. value /= fmt->radix;
  666. if ((i++ % 3) == 0 && value > 0) {
  667. *--cp = ',';
  668. }
  669. } while (value > 0);
  670. } else {
  671. do {
  672. *--cp = '0' + (int) (value % fmt->radix);
  673. value /= fmt->radix;
  674. } while (value > 0);
  675. }
  676. len = (int) (endp - cp);
  677. fill = fmt->width - len;
  678. if (prefix != 0) {
  679. fill -= (int) slen(prefix);
  680. }
  681. leadingZeros = (fmt->precision > len) ? fmt->precision - len : 0;
  682. fill -= leadingZeros;
  683. if (!(fmt->flags & SPRINTF_LEFT)) {
  684. c = (fmt->flags & SPRINTF_LEAD_ZERO) ? '0': ' ';
  685. for (i = 0; i < fill; i++) {
  686. BPUT(fmt, c);
  687. }
  688. }
  689. if (prefix != 0) {
  690. while (*prefix) {
  691. BPUT(fmt, *prefix++);
  692. }
  693. }
  694. for (i = 0; i < leadingZeros; i++) {
  695. BPUT(fmt, '0');
  696. }
  697. while (*cp) {
  698. BPUT(fmt, *cp);
  699. cp++;
  700. }
  701. if (fmt->flags & SPRINTF_LEFT) {
  702. for (i = 0; i < fill; i++) {
  703. BPUT(fmt, ' ');
  704. }
  705. }
  706. }
  707. #if ME_FLOAT
  708. static void outFloat(Format *fmt, char specChar, double value)
  709. {
  710. char result[ME_GOAHEAD_LIMIT_STRING], *cp;
  711. int c, fill, i, len, index;
  712. result[0] = '\0';
  713. if (specChar == 'f') {
  714. sprintf(result, "%.*f", fmt->precision, value);
  715. } else if (specChar == 'g') {
  716. sprintf(result, "%*.*g", fmt->width, fmt->precision, value);
  717. } else if (specChar == 'e') {
  718. sprintf(result, "%*.*e", fmt->width, fmt->precision, value);
  719. }
  720. len = (int) slen(result);
  721. fill = fmt->width - len;
  722. if (fmt->flags & SPRINTF_COMMA) {
  723. if (((len - 1) / 3) > 0) {
  724. fill -= (len - 1) / 3;
  725. }
  726. }
  727. if (fmt->flags & SPRINTF_SIGN && value > 0) {
  728. BPUT(fmt, '+');
  729. fill--;
  730. }
  731. if (!(fmt->flags & SPRINTF_LEFT)) {
  732. c = (fmt->flags & SPRINTF_LEAD_ZERO) ? '0': ' ';
  733. for (i = 0; i < fill; i++) {
  734. BPUT(fmt, c);
  735. }
  736. }
  737. index = len;
  738. for (cp = result; *cp; cp++) {
  739. BPUT(fmt, *cp);
  740. if (fmt->flags & SPRINTF_COMMA) {
  741. if ((--index % 3) == 0 && index > 0) {
  742. BPUT(fmt, ',');
  743. }
  744. }
  745. }
  746. if (fmt->flags & SPRINTF_LEFT) {
  747. for (i = 0; i < fill; i++) {
  748. BPUT(fmt, ' ');
  749. }
  750. }
  751. BPUTNULL(fmt);
  752. }
  753. #endif /* ME_FLOAT */
  754. /*
  755. Grow the buffer to fit new data. Return 1 if the buffer can grow.
  756. Grow using the growBy size specified when creating the buffer.
  757. */
  758. static int growBuf(Format *fmt)
  759. {
  760. uchar *newbuf;
  761. ssize buflen;
  762. buflen = (int) (fmt->endbuf - fmt->buf);
  763. if (fmt->maxsize >= 0 && buflen >= fmt->maxsize) {
  764. return 0;
  765. }
  766. if (fmt->growBy <= 0) {
  767. /*
  768. User supplied buffer
  769. */
  770. return 0;
  771. }
  772. if ((newbuf = walloc(buflen + fmt->growBy)) == 0) {
  773. return -1;
  774. }
  775. if (fmt->buf) {
  776. memcpy(newbuf, fmt->buf, buflen);
  777. wfree(fmt->buf);
  778. }
  779. buflen += fmt->growBy;
  780. fmt->end = newbuf + (fmt->end - fmt->buf);
  781. fmt->start = newbuf + (fmt->start - fmt->buf);
  782. fmt->buf = newbuf;
  783. fmt->endbuf = &fmt->buf[buflen];
  784. /*
  785. Increase growBy to reduce overhead
  786. */
  787. if ((buflen + (fmt->growBy * 2)) < fmt->maxsize) {
  788. fmt->growBy *= 2;
  789. }
  790. return 1;
  791. }
  792. WebsValue valueInteger(long value)
  793. {
  794. WebsValue v;
  795. memset(&v, 0x0, sizeof(v));
  796. v.valid = 1;
  797. v.type = integer;
  798. v.value.integer = value;
  799. return v;
  800. }
  801. WebsValue valueSymbol(void *value)
  802. {
  803. WebsValue v;
  804. memset(&v, 0x0, sizeof(v));
  805. v.valid = 1;
  806. v.type = symbol;
  807. v.value.symbol = value;
  808. return v;
  809. }
  810. WebsValue valueString(char *value, int flags)
  811. {
  812. WebsValue v;
  813. memset(&v, 0x0, sizeof(v));
  814. v.valid = 1;
  815. v.type = string;
  816. if (flags & VALUE_ALLOCATE) {
  817. v.allocated = 1;
  818. v.value.string = sclone(value);
  819. } else {
  820. v.allocated = 0;
  821. v.value.string = value;
  822. }
  823. return v;
  824. }
  825. PUBLIC void valueFree(WebsValue* v)
  826. {
  827. if (v->valid && v->allocated && v->type == string && v->value.string != NULL) {
  828. wfree(v->value.string);
  829. }
  830. v->type = undefined;
  831. v->valid = 0;
  832. v->allocated = 0;
  833. }
  834. #if ME_GOAHEAD_LOGGING
  835. static void defaultLogHandler(int flags, char *buf)
  836. {
  837. char prefix[ME_GOAHEAD_LIMIT_STRING];
  838. if (logFd >= 0) {
  839. if (flags & WEBS_RAW_MSG) {
  840. write(logFd, buf, (int) slen(buf));
  841. } else {
  842. fmt(prefix, sizeof(prefix), "%s: %d: ", ME_NAME, flags & WEBS_LEVEL_MASK);
  843. write(logFd, prefix, (int) slen(prefix));
  844. write(logFd, buf, (int) slen(buf));
  845. write(logFd, "\n", 1);
  846. #if ME_WIN_LIKE || ME_UNIX_LIKE
  847. if (flags & WEBS_ERROR_MSG && websGetBackground()) {
  848. syslog(LOG_ERR, "%s", buf);
  849. }
  850. #endif
  851. }
  852. }
  853. }
  854. PUBLIC void error(char *fmt, ...)
  855. {
  856. va_list args;
  857. char *message;
  858. if (!logHandler) {
  859. return;
  860. }
  861. va_start(args, fmt);
  862. message = sfmtv(fmt, args);
  863. va_end(args);
  864. logHandler(WEBS_ERROR_MSG, message);
  865. wfree(message);
  866. }
  867. PUBLIC void assertError(WEBS_ARGS_DEC, char *fmt, ...)
  868. {
  869. va_list args;
  870. char *fmtBuf, *message;
  871. va_start(args, fmt);
  872. fmtBuf = sfmtv(fmt, args);
  873. message = sfmt("Assertion %s, failed at %s %d\n", fmtBuf, WEBS_ARGS);
  874. va_end(args);
  875. wfree(fmtBuf);
  876. if (logHandler) {
  877. logHandler(WEBS_ASSERT_MSG, message);
  878. }
  879. wfree(message);
  880. }
  881. PUBLIC void logmsgProc(int level, char *fmt, ...)
  882. {
  883. va_list args;
  884. char *message;
  885. if ((level & WEBS_LEVEL_MASK) <= logLevel && logHandler) {
  886. va_start(args, fmt);
  887. message = sfmtv(fmt, args);
  888. logHandler(level | WEBS_LOG_MSG, message);
  889. wfree(message);
  890. va_end(args);
  891. }
  892. }
  893. PUBLIC void traceProc(int level, char *fmt, ...)
  894. {
  895. va_list args;
  896. char *message;
  897. if ((level & WEBS_LEVEL_MASK) <= logLevel && logHandler) {
  898. va_start(args, fmt);
  899. message = sfmtv(fmt, args);
  900. logHandler(level | WEBS_TRACE_MSG, message);
  901. wfree(message);
  902. va_end(args);
  903. }
  904. }
  905. PUBLIC int websGetLogLevel()
  906. {
  907. return logLevel;
  908. }
  909. void websSetLogLevel(int level)
  910. {
  911. logLevel = level;
  912. }
  913. WebsLogHandler logGetHandler()
  914. {
  915. return logHandler;
  916. }
  917. /*
  918. Replace the default trace handler. Return a pointer to the old handler.
  919. */
  920. WebsLogHandler logSetHandler(WebsLogHandler handler)
  921. {
  922. WebsLogHandler oldHandler;
  923. oldHandler = logHandler;
  924. if (handler) {
  925. logHandler = handler;
  926. }
  927. return oldHandler;
  928. }
  929. PUBLIC int logOpen()
  930. {
  931. if (!logPath) {
  932. /* This defintion comes from main.me goahead.logfile */
  933. logSetPath(ME_GOAHEAD_LOGFILE);
  934. }
  935. if (smatch(logPath, "stdout")) {
  936. logFd = 1;
  937. } else if (smatch(logPath, "stderr")) {
  938. logFd = 2;
  939. #if !ME_ROM
  940. } else {
  941. if ((logFd = open(logPath, O_CREAT | O_TRUNC | O_APPEND | O_WRONLY, 0666)) < 0) {
  942. return -1;
  943. }
  944. lseek(logFd, 0, SEEK_END);
  945. #endif
  946. }
  947. logSetHandler(logHandler);
  948. return 0;
  949. }
  950. PUBLIC void logClose()
  951. {
  952. #if !ME_ROM
  953. if (logFd > 2) {
  954. close(logFd);
  955. logFd = -1;
  956. }
  957. #endif
  958. }
  959. PUBLIC void logSetPath(char *path)
  960. {
  961. char *lp;
  962. wfree(logPath);
  963. logPath = sclone(path);
  964. if ((lp = strchr(logPath, ':')) != 0) {
  965. *lp++ = '\0';
  966. logLevel = atoi(lp);
  967. }
  968. }
  969. #endif
  970. /*
  971. Convert a string to lower case
  972. */
  973. PUBLIC char *slower(char *string)
  974. {
  975. char *s;
  976. if (string == NULL) {
  977. return NULL;
  978. }
  979. s = string;
  980. while (*s) {
  981. if (isupper(*s)) {
  982. *s = (char) tolower((uchar) *s);
  983. }
  984. s++;
  985. }
  986. *s = '\0';
  987. return string;
  988. }
  989. /*
  990. Convert a string to upper case
  991. */
  992. PUBLIC char *supper(char *string)
  993. {
  994. char *s;
  995. if (string == NULL) {
  996. return NULL;
  997. }
  998. s = string;
  999. while (*s) {
  1000. if (islower((uchar) *s)) {
  1001. *s = (char) toupper((uchar) *s);
  1002. }
  1003. s++;
  1004. }
  1005. *s = '\0';
  1006. return string;
  1007. }
  1008. PUBLIC char *itosbuf(char *buf, ssize size, int64 value, int radix)
  1009. {
  1010. char *cp, *end;
  1011. char digits[] = "0123456789ABCDEF";
  1012. int negative;
  1013. if ((radix != 10 && radix != 16) || size < 2) {
  1014. return 0;
  1015. }
  1016. end = cp = &buf[size];
  1017. *--cp = '\0';
  1018. if (value < 0) {
  1019. negative = 1;
  1020. value = -value;
  1021. size--;
  1022. } else {
  1023. negative = 0;
  1024. }
  1025. do {
  1026. *--cp = digits[value % radix];
  1027. value /= radix;
  1028. } while (value > 0 && cp > buf);
  1029. if (negative) {
  1030. if (cp <= buf) {
  1031. return 0;
  1032. }
  1033. *--cp = '-';
  1034. }
  1035. if (buf < cp) {
  1036. /* Move the null too */
  1037. memmove(buf, cp, end - cp);
  1038. }
  1039. return buf;
  1040. }
  1041. /*
  1042. Allocate a new file handle. On the first call, the caller must set the handle map to be a pointer to a null
  1043. pointer. map points to the second element in the handle array.
  1044. */
  1045. PUBLIC int wallocHandle(void *mapArg)
  1046. {
  1047. void ***map;
  1048. ssize *mp;
  1049. int handle, len, memsize, incr;
  1050. map = (void***) mapArg;
  1051. assert(map);
  1052. if (*map == NULL) {
  1053. incr = H_INCR;
  1054. memsize = (incr + H_OFFSET) * sizeof(void*);
  1055. if ((mp = walloc(memsize)) == NULL) {
  1056. return -1;
  1057. }
  1058. memset(mp, 0, memsize);
  1059. mp[H_LEN] = incr;
  1060. mp[H_USED] = 0;
  1061. *map = (void*) &mp[H_OFFSET];
  1062. } else {
  1063. mp = &((*(ssize**)map)[-H_OFFSET]);
  1064. }
  1065. len = (int) mp[H_LEN];
  1066. /*
  1067. Find the first null handle
  1068. */
  1069. if (mp[H_USED] < mp[H_LEN]) {
  1070. for (handle = 0; handle < len; handle++) {
  1071. if (mp[handle + H_OFFSET] == 0) {
  1072. mp[H_USED]++;
  1073. return handle;
  1074. }
  1075. }
  1076. } else {
  1077. handle = len;
  1078. }
  1079. /*
  1080. No free handle so grow the handle list. Grow list in chunks of H_INCR.
  1081. */
  1082. len += H_INCR;
  1083. memsize = (len + H_OFFSET) * sizeof(void*);
  1084. if ((mp = wrealloc(mp, memsize)) == NULL) {
  1085. return -1;
  1086. }
  1087. *map = (void*) &mp[H_OFFSET];
  1088. mp[H_LEN] = len;
  1089. memset(&mp[H_OFFSET + len - H_INCR], 0, sizeof(ssize*) * H_INCR);
  1090. mp[H_USED]++;
  1091. return handle;
  1092. }
  1093. /*
  1094. Free a handle. This function returns the value of the largest handle in use plus 1, to be saved as a max value.
  1095. */
  1096. PUBLIC int wfreeHandle(void *mapArg, int handle)
  1097. {
  1098. void ***map;
  1099. ssize *mp;
  1100. int len;
  1101. map = (void***) mapArg;
  1102. assert(map);
  1103. mp = &((*(ssize**)map)[-H_OFFSET]);
  1104. assert(mp[H_LEN] >= H_INCR);
  1105. assert(mp[handle + H_OFFSET]);
  1106. assert(mp[H_USED]);
  1107. mp[handle + H_OFFSET] = 0;
  1108. if (--(mp[H_USED]) == 0) {
  1109. wfree((void*) mp);
  1110. *map = NULL;
  1111. }
  1112. /*
  1113. Find the greatest handle number in use.
  1114. */
  1115. if (*map == NULL) {
  1116. handle = -1;
  1117. } else {
  1118. len = (int) mp[H_LEN];
  1119. if (mp[H_USED] < mp[H_LEN]) {
  1120. for (handle = len - 1; handle >= 0; handle--) {
  1121. if (mp[handle + H_OFFSET])
  1122. break;
  1123. }
  1124. } else {
  1125. handle = len;
  1126. }
  1127. }
  1128. return handle + 1;
  1129. }
  1130. /*
  1131. Allocate an entry in the halloc array
  1132. */
  1133. PUBLIC int wallocObject(void *listArg, int *max, int size)
  1134. {
  1135. void ***list;
  1136. char *cp;
  1137. int id;
  1138. list = (void***) listArg;
  1139. assert(list);
  1140. assert(max);
  1141. if ((id = wallocHandle(list)) < 0) {
  1142. return -1;
  1143. }
  1144. if (size > 0) {
  1145. if ((cp = walloc(size)) == NULL) {
  1146. wfreeHandle(list, id);
  1147. return -1;
  1148. }
  1149. assert(cp);
  1150. memset(cp, 0, size);
  1151. (*list)[id] = (void*) cp;
  1152. }
  1153. if (id >= *max) {
  1154. *max = id + 1;
  1155. }
  1156. return id;
  1157. }
  1158. /*
  1159. Create a new buf. "increment" is the amount to increase the size of the buf should it need to grow to accomodate
  1160. data being added. "maxsize" is an upper limit (sanity level) beyond which the buffer must not grow. Set maxsize to -1 to
  1161. imply no upper limit. The buffer for the buf is always * dynamically allocated. Set maxsize
  1162. */
  1163. PUBLIC int bufCreate(WebsBuf *bp, int initSize, int maxsize)
  1164. {
  1165. int increment;
  1166. assert(bp);
  1167. if (initSize <= 0) {
  1168. initSize = ME_GOAHEAD_LIMIT_BUFFER;
  1169. }
  1170. if (maxsize <= 0) {
  1171. maxsize = initSize;
  1172. }
  1173. assert(initSize >= 0);
  1174. increment = getBinBlockSize(initSize);
  1175. if ((bp->buf = walloc((increment))) == NULL) {
  1176. return -1;
  1177. }
  1178. bp->maxsize = maxsize;
  1179. bp->buflen = increment;
  1180. bp->increment = increment;
  1181. bp->endbuf = &bp->buf[bp->buflen];
  1182. bp->servp = bp->buf;
  1183. bp->endp = bp->buf;
  1184. *bp->servp = '\0';
  1185. return 0;
  1186. }
  1187. /*
  1188. Delete a buf and free the buf buffer.
  1189. */
  1190. PUBLIC void bufFree(WebsBuf *bp)
  1191. {
  1192. assert(bp);
  1193. assert(bp->buflen == (bp->endbuf - bp->buf));
  1194. if (bp == NULL) {
  1195. return;
  1196. }
  1197. bufFlush(bp);
  1198. wfree((char*) bp->buf);
  1199. bp->buf = NULL;
  1200. }
  1201. /*
  1202. Return the length of the data in the buf. Users must fill the queue to a high water mark of at most one less than
  1203. the queue size.
  1204. */
  1205. PUBLIC ssize bufLen(WebsBuf *bp)
  1206. {
  1207. assert(bp);
  1208. assert(bp->buflen == (bp->endbuf - bp->buf));
  1209. if (bp->servp > bp->endp) {
  1210. return bp->buflen + bp->endp - bp->servp;
  1211. } else {
  1212. return bp->endp - bp->servp;
  1213. }
  1214. }
  1215. /*
  1216. Return the reference to the start of data in the buffer
  1217. */
  1218. PUBLIC char *bufStart(WebsBuf *bp)
  1219. {
  1220. assert(bp);
  1221. return bp->servp;
  1222. }
  1223. /*
  1224. Get a byte from the queue
  1225. */
  1226. PUBLIC int bufGetc(WebsBuf *bp)
  1227. {
  1228. char c, *cp;
  1229. assert(bp);
  1230. assert(bp->buflen == (bp->endbuf - bp->buf));
  1231. if (bp->servp == bp->endp) {
  1232. return -1;
  1233. }
  1234. cp = (char*) bp->servp;
  1235. c = *cp++;
  1236. bp->servp = cp;
  1237. if (bp->servp >= bp->endbuf) {
  1238. bp->servp = bp->buf;
  1239. }
  1240. return (int) ((uchar) c);
  1241. }
  1242. /*
  1243. Add a char to the queue. Note if being used to store wide strings this does not add a trailing '\0'. Grow the buffer as
  1244. required.
  1245. */
  1246. PUBLIC int bufPutc(WebsBuf *bp, char c)
  1247. {
  1248. char *cp;
  1249. assert(bp);
  1250. assert(bp->buflen == (bp->endbuf - bp->buf));
  1251. if ((bufRoom(bp) < (int) sizeof(char)) && !bufGrow(bp, 0)) {
  1252. return -1;
  1253. }
  1254. cp = (char*) bp->endp;
  1255. *cp++ = (char) c;
  1256. bp->endp = cp;
  1257. if (bp->endp >= bp->endbuf) {
  1258. bp->endp = bp->buf;
  1259. }
  1260. return 0;
  1261. }
  1262. /*
  1263. Insert a wide character at the front of the queue
  1264. */
  1265. PUBLIC int bufInsertc(WebsBuf *bp, char c)
  1266. {
  1267. char *cp;
  1268. assert(bp);
  1269. assert(bp->buflen == (bp->endbuf - bp->buf));
  1270. if (bufRoom(bp) < (int) sizeof(char) && !bufGrow(bp, 0)) {
  1271. return -1;
  1272. }
  1273. if (bp->servp <= bp->buf) {
  1274. bp->servp = bp->endbuf;
  1275. }
  1276. cp = (char*) bp->servp;
  1277. *--cp = (char) c;
  1278. bp->servp = cp;
  1279. return 0;
  1280. }
  1281. PUBLIC ssize bufPut(WebsBuf *bp, char *fmt, ...)
  1282. {
  1283. va_list ap;
  1284. char *str;
  1285. ssize rc;
  1286. assert(bp);
  1287. assert(bp->buflen == (bp->endbuf - bp->buf));
  1288. if (fmt == 0) {
  1289. return 0;
  1290. }
  1291. va_start(ap, fmt);
  1292. str = sfmtv(fmt, ap);
  1293. va_end(ap);
  1294. //printf("---> bufPutBlk6 len = %d\n", strlen(str) * sizeof(char));
  1295. rc = bufPutBlk(bp, str, strlen(str) * sizeof(char));
  1296. *((char*) bp->endp) = (char) '\0';
  1297. return rc;
  1298. }
  1299. /*
  1300. Add a string to the queue. Add a trailing null (maybe two nulls)
  1301. */
  1302. PUBLIC ssize bufPutStr(WebsBuf *bp, char *str)
  1303. {
  1304. ssize rc;
  1305. assert(bp);
  1306. assert(str);
  1307. assert(bp->buflen == (bp->endbuf - bp->buf));
  1308. //printf("---> bufPutBlk9 len = %d, str = %s\n", strlen(str) * sizeof(char), str);
  1309. rc = bufPutBlk(bp, str, strlen(str) * sizeof(char));
  1310. *((char*) bp->endp) = (char) '\0';
  1311. return rc;
  1312. }
  1313. /*
  1314. Add a null terminator. This does NOT increase the size of the queue
  1315. */
  1316. PUBLIC void bufAddNull(WebsBuf *bp)
  1317. {
  1318. assert(bp);
  1319. assert(bp->buflen == (bp->endbuf - bp->buf));
  1320. if (bufRoom(bp) < (int) sizeof(char)) {
  1321. bufGrow(bp, 0);
  1322. return;
  1323. }
  1324. *((char*) bp->endp) = (char) '\0';
  1325. }
  1326. #if UNICODE
  1327. /*
  1328. Get a byte from the queue
  1329. */
  1330. PUBLIC int bufGetcA(WebsBuf *bp)
  1331. {
  1332. uchar c;
  1333. assert(bp);
  1334. assert(bp->buflen == (bp->endbuf - bp->buf));
  1335. if (bp->servp == bp->endp) {
  1336. return -1;
  1337. }
  1338. c = *bp->servp++;
  1339. if (bp->servp >= bp->endbuf) {
  1340. bp->servp = bp->buf;
  1341. }
  1342. return c;
  1343. }
  1344. /*
  1345. Add a byte to the queue. Note if being used to store strings this does not add a trailing '\0'.
  1346. Grow the buffer as required.
  1347. */
  1348. PUBLIC int bufPutcA(WebsBuf *bp, char c)
  1349. {
  1350. assert(bp);
  1351. assert(bp->buflen == (bp->endbuf - bp->buf));
  1352. if (bufRoom(bp) == 0 && !bufGrow(bp)) {
  1353. return -1;
  1354. }
  1355. *bp->endp++ = (uchar) c;
  1356. if (bp->endp >= bp->endbuf) {
  1357. bp->endp = bp->buf;
  1358. }
  1359. return 0;
  1360. }
  1361. /*
  1362. Insert a byte at the front of the queue
  1363. */
  1364. PUBLIC int bufInsertcA(WebsBuf *bp, char c)
  1365. {
  1366. assert(bp);
  1367. assert(bp->buflen == (bp->endbuf - bp->buf));
  1368. if (bufRoom(bp) == 0 && !bufGrow(bp)) {
  1369. return -1;
  1370. }
  1371. if (bp->servp <= bp->buf) {
  1372. bp->servp = bp->endbuf;
  1373. }
  1374. *--bp->servp = (uchar) c;
  1375. return 0;
  1376. }
  1377. /*
  1378. Add a string to the queue. Add a trailing null (not really in the q). ie. beyond the last valid byte.
  1379. */
  1380. PUBLIC int bufPutStrA(WebsBuf *bp, char *str)
  1381. {
  1382. int rc;
  1383. assert(bp);
  1384. assert(str);
  1385. assert(bp->buflen == (bp->endbuf - bp->buf));
  1386. //printf("---> bufPutBlk7 len = %d, str = %s\n", strlen(str), str);
  1387. rc = (int) bufPutBlk(bp, str, strlen(str));
  1388. bp->endp[0] = '\0';
  1389. return rc;
  1390. }
  1391. #endif
  1392. /*
  1393. Add a block of data to the buf. Return the number of bytes added. Grow the buffer as required.
  1394. */
  1395. PUBLIC ssize bufPutBlk(WebsBuf *bp, char *buf, ssize size)
  1396. {
  1397. ssize this, added;
  1398. assert(bp);
  1399. assert(bp->buflen == (bp->endbuf - bp->buf));
  1400. assert(buf);
  1401. assert(0 <= size);
  1402. /*
  1403. Loop adding the maximum bytes we can add in a single straight line copy
  1404. */
  1405. added = 0;
  1406. while (size > 0) {
  1407. this = min(bufRoom(bp), size);
  1408. if (this <= 0) {
  1409. if (! bufGrow(bp, 0)) {
  1410. break;
  1411. }
  1412. this = min(bufRoom(bp), size);
  1413. }
  1414. memcpy(bp->endp, buf, this);
  1415. buf += this;
  1416. bp->endp += this;
  1417. size -= this;
  1418. added += this;
  1419. if (bp->endp >= bp->endbuf) {
  1420. bp->endp = bp->buf;
  1421. }
  1422. }
  1423. return added;
  1424. }
  1425. /*
  1426. Get a block of data from the buf. Return the number of bytes returned.
  1427. */
  1428. PUBLIC ssize bufGetBlk(WebsBuf *bp, char *buf, ssize size)
  1429. {
  1430. ssize this, bytes_read;
  1431. // printf("---> bufGetBlk, size: %d, buflen: %d, endbuf: %p, buf: %p\n", bp->buflen, bp->endbuf, bp->buf);
  1432. assert(bp);
  1433. assert(bp->buflen == (bp->endbuf - bp->buf));
  1434. assert(buf);
  1435. assert(0 <= size && size < bp->buflen);
  1436. /*
  1437. Loop getting the maximum bytes we can get in a single straight line copy
  1438. */
  1439. bytes_read = 0;
  1440. while (size > 0) {
  1441. this = bufGetBlkMax(bp);
  1442. this = min(this, size);
  1443. if (this <= 0) {
  1444. break;
  1445. }
  1446. memcpy(buf, bp->servp, this);
  1447. buf += this;
  1448. bp->servp += this;
  1449. size -= this;
  1450. bytes_read += this;
  1451. if (bp->servp >= bp->endbuf) {
  1452. bp->servp = bp->buf;
  1453. }
  1454. }
  1455. return bytes_read;
  1456. }
  1457. /*
  1458. Return the maximum number of bytes the buffer can accept via a single block copy. Useful if the user is doing their
  1459. own data insertion.
  1460. */
  1461. PUBLIC ssize bufRoom(WebsBuf *bp)
  1462. {
  1463. ssize space, in_a_line;
  1464. assert(bp);
  1465. assert(bp->buflen == (bp->endbuf - bp->buf));
  1466. space = bp->buflen - RINGQ_LEN(bp) - 1;
  1467. in_a_line = bp->endbuf - bp->endp;
  1468. return min(in_a_line, space);
  1469. }
  1470. /*
  1471. Return the maximum number of bytes the buffer can provide via a single block copy. Useful if the user is doing their
  1472. own data retrieval.
  1473. */
  1474. PUBLIC ssize bufGetBlkMax(WebsBuf *bp)
  1475. {
  1476. ssize len, in_a_line;
  1477. assert(bp);
  1478. assert(bp->buflen == (bp->endbuf - bp->buf));
  1479. len = RINGQ_LEN(bp);
  1480. in_a_line = bp->endbuf - bp->servp;
  1481. return min(in_a_line, len);
  1482. }
  1483. /*
  1484. Adjust the endp pointer after the user has copied data into the queue.
  1485. */
  1486. PUBLIC void bufAdjustEnd(WebsBuf *bp, ssize size)
  1487. {
  1488. // printf("---> bufAdjustEnd, size: %d, buflen: %d, endbuf: %p, buf: %p\n", size, bp->buflen, bp->endbuf, bp->buf);
  1489. assert(bp);
  1490. assert(bp->buflen == (bp->endbuf - bp->buf));
  1491. assert(0 <= size && size < bp->buflen);
  1492. bp->endp += size;
  1493. if (bp->endp >= bp->endbuf) {
  1494. bp->endp -= bp->buflen;
  1495. }
  1496. /*
  1497. Flush the queue if the endp pointer is corrupted via a bad size
  1498. */
  1499. if (bp->endp >= bp->endbuf) {
  1500. error("Bad end pointer");
  1501. bufFlush(bp);
  1502. }
  1503. }
  1504. /*
  1505. Adjust the servp pointer after the user has copied data from the queue.
  1506. */
  1507. PUBLIC void bufAdjustStart(WebsBuf *bp, ssize size)
  1508. {
  1509. //printf("---> bufAdjustStart, size: %d, buflen: %d, endbuf: %p, buf: %p\n", size, bp->buflen, bp->endbuf, bp->buf);
  1510. assert(bp);
  1511. assert(bp->buflen == (bp->endbuf - bp->buf));
  1512. assert(0 <= size && size < bp->buflen);
  1513. bp->servp += size;
  1514. if (bp->servp >= bp->endbuf) {
  1515. bp->servp -= bp->buflen;
  1516. }
  1517. /*
  1518. Flush the queue if the servp pointer is corrupted via a bad size
  1519. */
  1520. if (bp->servp >= bp->endbuf) {
  1521. error("Bad serv pointer");
  1522. bufFlush(bp);
  1523. }
  1524. }
  1525. /*
  1526. Flush all data in a buffer. Reset the pointers.
  1527. */
  1528. PUBLIC void bufFlush(WebsBuf *bp)
  1529. {
  1530. assert(bp);
  1531. assert(bp->servp);
  1532. if (bp->buf) {
  1533. bp->servp = bp->buf;
  1534. bp->endp = bp->buf;
  1535. if (bp->servp) {
  1536. *bp->servp = '\0';
  1537. }
  1538. }
  1539. }
  1540. PUBLIC void bufCompact(WebsBuf *bp)
  1541. {
  1542. ssize len;
  1543. if (bp->buf) {
  1544. if ((len = bufLen(bp)) > 0) {
  1545. if (bp->servp < bp->endp && bp->servp > bp->buf) {
  1546. bufAddNull(bp);
  1547. memmove(bp->buf, bp->servp, len + 1);
  1548. bp->endp -= bp->servp - bp->buf;
  1549. bp->servp = bp->buf;
  1550. }
  1551. } else {
  1552. bp->servp = bp->endp = bp->buf;
  1553. *bp->servp = '\0';
  1554. }
  1555. }
  1556. }
  1557. /*
  1558. Reset pointers if empty
  1559. */
  1560. PUBLIC void bufReset(WebsBuf *bp)
  1561. {
  1562. if (bp->buf && bp->servp == bp->endp && bp->servp > bp->buf) {
  1563. bp->servp = bp->endp = bp->buf;
  1564. *bp->servp = '\0';
  1565. }
  1566. }
  1567. /*
  1568. Grow the buffer. Return true if the buffer can be grown. Grow using the increment size specified when opening the
  1569. buf. Don't grow beyond the maximum possible size.
  1570. */
  1571. PUBLIC bool bufGrow(WebsBuf *bp, ssize room)
  1572. {
  1573. char *newbuf;
  1574. ssize len;
  1575. assert(bp);
  1576. if (room == 0) {
  1577. if (bp->maxsize >= 0 && bp->buflen >= bp->maxsize) {
  1578. #if BLD_DEBUG
  1579. error("Cannot grow buf. Needed %d, max %d", room, bp->maxsize);
  1580. #endif
  1581. return 0;
  1582. }
  1583. room = bp->increment;
  1584. /*
  1585. Double the increment so the next grow will line up with walloc'ed memory
  1586. */
  1587. bp->increment = getBinBlockSize(2 * bp->increment);
  1588. }
  1589. len = bufLen(bp);
  1590. if ((newbuf = walloc(bp->buflen + room)) == NULL) {
  1591. return 0;
  1592. }
  1593. bufGetBlk(bp, newbuf, bufLen(bp));
  1594. wfree((char*) bp->buf);
  1595. bp->buflen += room;
  1596. bp->buf = newbuf;
  1597. bp->endbuf = &bp->buf[bp->buflen];
  1598. bp->servp = newbuf;
  1599. bp->endp = &newbuf[len];
  1600. return 1;
  1601. }
  1602. /*
  1603. Find the smallest binary memory size that "size" will fit into. This makes the buf and bufGrow routines much
  1604. more efficient. The walloc routine likes powers of 2 minus 1.
  1605. */
  1606. static int getBinBlockSize(int size)
  1607. {
  1608. int q;
  1609. size = size >> WEBS_SHIFT;
  1610. for (q = 0; size; size >>= 1) {
  1611. q++;
  1612. }
  1613. return (1 << (WEBS_SHIFT + q));
  1614. }
  1615. WebsHash hashCreate(int size)
  1616. {
  1617. WebsHash sd;
  1618. HashTable *tp;
  1619. if (size < 0) {
  1620. size = WEBS_SMALL_HASH;
  1621. }
  1622. assert(size > 2);
  1623. /*
  1624. Create a new handle for this symbol table
  1625. */
  1626. if ((sd = wallocHandle(&sym)) < 0) {
  1627. return -1;
  1628. }
  1629. /*
  1630. Create a new symbol table structure and zero
  1631. */
  1632. if ((tp = (HashTable*) walloc(sizeof(HashTable))) == NULL) {
  1633. symMax = wfreeHandle(&sym, sd);
  1634. return -1;
  1635. }
  1636. memset(tp, 0, sizeof(HashTable));
  1637. if (sd >= symMax) {
  1638. symMax = sd + 1;
  1639. }
  1640. assert(0 <= sd && sd < symMax);
  1641. sym[sd] = tp;
  1642. /*
  1643. Now create the hash table for fast indexing.
  1644. */
  1645. tp->size = calcPrime(size);
  1646. if ((tp->hash_table = (WebsKey**) walloc(tp->size * sizeof(WebsKey*))) == 0) {
  1647. wfreeHandle(&sym, sd);
  1648. wfree(tp);
  1649. return -1;
  1650. }
  1651. assert(tp->hash_table);
  1652. memset(tp->hash_table, 0, tp->size * sizeof(WebsKey*));
  1653. return sd;
  1654. }
  1655. /*
  1656. Close this symbol table. Call a cleanup function to allow the caller to free resources associated with each symbol
  1657. table entry.
  1658. */
  1659. PUBLIC void hashFree(WebsHash sd)
  1660. {
  1661. HashTable *tp;
  1662. WebsKey *sp, *forw;
  1663. int i;
  1664. if (sd < 0) {
  1665. return;
  1666. }
  1667. assert(0 <= sd && sd < symMax);
  1668. tp = sym[sd];
  1669. assert(tp);
  1670. /*
  1671. Free all symbols in the hash table, then the hash table itself.
  1672. */
  1673. for (i = 0; i < tp->size; i++) {
  1674. for (sp = tp->hash_table[i]; sp; sp = forw) {
  1675. forw = sp->forw;
  1676. valueFree(&sp->name);
  1677. valueFree(&sp->content);
  1678. wfree((void*) sp);
  1679. sp = forw;
  1680. }
  1681. }
  1682. wfree((void*) tp->hash_table);
  1683. symMax = wfreeHandle(&sym, sd);
  1684. wfree((void*) tp);
  1685. }
  1686. /*
  1687. Return the first symbol in the hashtable if there is one. This call is used as the first step in traversing the
  1688. table. A call to hashFirst should be followed by calls to hashNext to get all the rest of the entries.
  1689. */
  1690. WebsKey *hashFirst(WebsHash sd)
  1691. {
  1692. HashTable *tp;
  1693. WebsKey *sp;
  1694. int i;
  1695. assert(0 <= sd && sd < symMax);
  1696. tp = sym[sd];
  1697. assert(tp);
  1698. /*
  1699. Find the first symbol in the hashtable and return a pointer to it.
  1700. */
  1701. for (i = 0; i < tp->size; i++) {
  1702. if ((sp = tp->hash_table[i]) != 0) {
  1703. return sp;
  1704. }
  1705. }
  1706. return 0;
  1707. }
  1708. /*
  1709. Return the next symbol in the hashtable if there is one. See hashFirst.
  1710. */
  1711. WebsKey *hashNext(WebsHash sd, WebsKey *last)
  1712. {
  1713. HashTable *tp;
  1714. WebsKey *sp;
  1715. int i;
  1716. assert(0 <= sd && sd < symMax);
  1717. if (sd < 0) {
  1718. return 0;
  1719. }
  1720. tp = sym[sd];
  1721. assert(tp);
  1722. if (last == 0) {
  1723. return hashFirst(sd);
  1724. }
  1725. if (last->forw) {
  1726. return last->forw;
  1727. }
  1728. for (i = last->bucket + 1; i < tp->size; i++) {
  1729. if ((sp = tp->hash_table[i]) != 0) {
  1730. return sp;
  1731. }
  1732. }
  1733. return NULL;
  1734. }
  1735. /*
  1736. Lookup a symbol and return a pointer to the symbol entry. If not present then return a NULL.
  1737. */
  1738. WebsKey *hashLookup(WebsHash sd, char *name)
  1739. {
  1740. HashTable *tp;
  1741. WebsKey *sp;
  1742. char *cp;
  1743. assert(0 <= sd && sd < symMax);
  1744. if (sd < 0 || (tp = sym[sd]) == NULL) {
  1745. return NULL;
  1746. }
  1747. if (name == NULL || *name == '\0') {
  1748. return NULL;
  1749. }
  1750. /*
  1751. Do an initial hash and then follow the link chain to find the right entry
  1752. */
  1753. for (sp = hash(tp, name); sp; sp = sp->forw) {
  1754. cp = sp->name.value.string;
  1755. if (cp[0] == name[0] && strcmp(cp, name) == 0) {
  1756. break;
  1757. }
  1758. }
  1759. return sp;
  1760. }
  1761. void *hashLookupSymbol(WebsHash sd, char *name)
  1762. {
  1763. WebsKey *kp;
  1764. if ((kp = hashLookup(sd, name)) == 0) {
  1765. return 0;
  1766. }
  1767. return kp->content.value.symbol;
  1768. }
  1769. /*
  1770. Enter a symbol into the table. If already there, update its value. Always succeeds if memory available. We allocate
  1771. a copy of "name" here so it can be a volatile variable. The value "v" is just a copy of the passed in value, so it
  1772. MUST be persistent.
  1773. */
  1774. WebsKey *hashEnter(WebsHash sd, char *name, WebsValue v, int arg)
  1775. {
  1776. HashTable *tp;
  1777. WebsKey *sp, *last;
  1778. char *cp;
  1779. int hindex;
  1780. assert(name);
  1781. assert(0 <= sd && sd < symMax);
  1782. tp = sym[sd];
  1783. assert(tp);
  1784. /*
  1785. Calculate the first daisy-chain from the hash table. If non-zero, then we have daisy-chain, so scan it and look
  1786. for the symbol.
  1787. */
  1788. last = NULL;
  1789. hindex = hashIndex(tp, name);
  1790. if ((sp = tp->hash_table[hindex]) != NULL) {
  1791. for (; sp; sp = sp->forw) {
  1792. cp = sp->name.value.string;
  1793. if (cp[0] == name[0] && strcmp(cp, name) == 0) {
  1794. break;
  1795. }
  1796. last = sp;
  1797. }
  1798. if (sp) {
  1799. /*
  1800. Found, so update the value If the caller stores handles which require freeing, they will be lost here.
  1801. It is the callers responsibility to free resources before overwriting existing contents. We will here
  1802. free allocated strings which occur due to value_instring(). We should consider providing the cleanup
  1803. function on the open rather than the close and then we could call it here and solve the problem.
  1804. */
  1805. if (sp->content.valid) {
  1806. valueFree(&sp->content);
  1807. }
  1808. sp->content = v;
  1809. sp->arg = arg;
  1810. return sp;
  1811. }
  1812. /*
  1813. Not found so allocate and append to the daisy-chain
  1814. */
  1815. if ((sp = (WebsKey*) walloc(sizeof(WebsKey))) == 0) {
  1816. return NULL;
  1817. }
  1818. sp->name = valueString(name, VALUE_ALLOCATE);
  1819. sp->content = v;
  1820. sp->forw = (WebsKey*) NULL;
  1821. sp->arg = arg;
  1822. sp->bucket = hindex;
  1823. last->forw = sp;
  1824. } else {
  1825. /*
  1826. Daisy chain is empty so we need to start the chain
  1827. */
  1828. if ((sp = (WebsKey*) walloc(sizeof(WebsKey))) == 0) {
  1829. return NULL;
  1830. }
  1831. tp->hash_table[hindex] = sp;
  1832. tp->hash_table[hashIndex(tp, name)] = sp;
  1833. sp->forw = (WebsKey*) NULL;
  1834. sp->content = v;
  1835. sp->arg = arg;
  1836. sp->name = valueString(name, VALUE_ALLOCATE);
  1837. sp->bucket = hindex;
  1838. }
  1839. return sp;
  1840. }
  1841. /*
  1842. Delete a symbol from a table
  1843. */
  1844. PUBLIC int hashDelete(WebsHash sd, char *name)
  1845. {
  1846. HashTable *tp;
  1847. WebsKey *sp, *last;
  1848. char *cp;
  1849. int hindex;
  1850. assert(name && *name);
  1851. assert(0 <= sd && sd < symMax);
  1852. tp = sym[sd];
  1853. assert(tp);
  1854. /*
  1855. Calculate the first daisy-chain from the hash table. If non-zero, then we have daisy-chain, so scan it and look
  1856. for the symbol.
  1857. */
  1858. last = NULL;
  1859. hindex = hashIndex(tp, name);
  1860. if ((sp = tp->hash_table[hindex]) != NULL) {
  1861. for ( ; sp; sp = sp->forw) {
  1862. cp = sp->name.value.string;
  1863. if (cp[0] == name[0] && strcmp(cp, name) == 0) {
  1864. break;
  1865. }
  1866. last = sp;
  1867. }
  1868. }
  1869. if (sp == (WebsKey*) NULL) { /* Not Found */
  1870. return -1;
  1871. }
  1872. /*
  1873. Unlink and free the symbol. Last will be set if the element to be deleted is not first in the chain.
  1874. */
  1875. if (last) {
  1876. last->forw = sp->forw;
  1877. } else {
  1878. tp->hash_table[hindex] = sp->forw;
  1879. }
  1880. valueFree(&sp->name);
  1881. valueFree(&sp->content);
  1882. wfree((void*) sp);
  1883. return 0;
  1884. }
  1885. /*
  1886. Hash a symbol and return a pointer to the hash daisy-chain list. All symbols reside on the chain (ie. none stored in
  1887. the hash table itself)
  1888. */
  1889. static WebsKey *hash(HashTable *tp, char *name)
  1890. {
  1891. assert(tp);
  1892. return tp->hash_table[hashIndex(tp, name)];
  1893. }
  1894. /*
  1895. Compute the hash function and return an index into the hash table We use a basic additive function that is then made
  1896. modulo the size of the table.
  1897. */
  1898. static int hashIndex(HashTable *tp, char *name)
  1899. {
  1900. uint sum;
  1901. int i;
  1902. assert(tp);
  1903. /*
  1904. Add in each character shifted up progressively by 7 bits. The shift amount is rounded so as to not shift too
  1905. far. It thus cycles with each new cycle placing character shifted up by one bit.
  1906. */
  1907. i = 0;
  1908. sum = 0;
  1909. while (*name) {
  1910. sum += (((int) *name++) << i);
  1911. i = (i + 7) % (BITS(int) - BITSPERBYTE);
  1912. }
  1913. return sum % tp->size;
  1914. }
  1915. /*
  1916. Check if this number is a prime
  1917. */
  1918. static int isPrime(int n)
  1919. {
  1920. int i, max;
  1921. assert(n > 0);
  1922. max = n / 2;
  1923. for (i = 2; i <= max; i++) {
  1924. if (n % i == 0) {
  1925. return 0;
  1926. }
  1927. }
  1928. return 1;
  1929. }
  1930. /*
  1931. Calculate the largest prime smaller than size.
  1932. */
  1933. static int calcPrime(int size)
  1934. {
  1935. int count;
  1936. assert(size > 0);
  1937. for (count = size; count > 0; count--) {
  1938. if (isPrime(count)) {
  1939. return count;
  1940. }
  1941. }
  1942. return 1;
  1943. }
  1944. #if DEPRECATE || 1
  1945. /*
  1946. Convert a wide unicode string into a multibyte string buffer. If count is supplied, it is used as the source length
  1947. in characters. Otherwise set to -1. DestCount is the max size of the dest buffer in bytes. At most destCount - 1
  1948. characters will be stored. The dest buffer will always have a trailing null appended. If dest is NULL, don't copy
  1949. the string, just return the length of characters. Return a count of bytes copied to the destination or -1 if an
  1950. invalid unicode sequence was provided in src.
  1951. NOTE: does not allocate.
  1952. */
  1953. PUBLIC ssize wtom(char *dest, ssize destCount, wchar *src, ssize count)
  1954. {
  1955. ssize len;
  1956. if (destCount < 0) {
  1957. destCount = MAXSSIZE;
  1958. }
  1959. if (count > 0) {
  1960. #if ME_CHAR_LEN == 1
  1961. if (dest) {
  1962. len = scopy(dest, destCount, src);
  1963. } else {
  1964. len = min(slen(src), destCount - 1);
  1965. }
  1966. #elif ME_WIN_LIKE
  1967. len = WideCharToMultiByte(CP_ACP, 0, src, count, dest, (DWORD) destCount - 1, NULL, NULL);
  1968. #else
  1969. len = wcstombs(dest, src, destCount - 1);
  1970. #endif
  1971. if (dest) {
  1972. if (len >= 0) {
  1973. dest[len] = 0;
  1974. }
  1975. } else if (len >= destCount) {
  1976. return -1;
  1977. }
  1978. } else {
  1979. len = 0;
  1980. }
  1981. return len;
  1982. }
  1983. /*
  1984. Convert a multibyte string to a unicode string. If count is supplied, it is used as the source length in bytes.
  1985. Otherwise set to -1. DestCount is the max size of the dest buffer in characters. At most destCount - 1
  1986. characters will be stored. The dest buffer will always have a trailing null characters appended. If dest is NULL,
  1987. don't copy the string, just return the length of characters. Return a count of characters copied to the destination
  1988. or -1 if an invalid multibyte sequence was provided in src.
  1989. NOTE: does not allocate.
  1990. */
  1991. PUBLIC ssize mtow(wchar *dest, ssize destCount, char *src, ssize count)
  1992. {
  1993. ssize len;
  1994. if (destCount < 0) {
  1995. destCount = MAXSSIZE;
  1996. }
  1997. if (destCount > 0) {
  1998. #if ME_CHAR_LEN == 1
  1999. if (dest) {
  2000. len = scopy(dest, destCount, src);
  2001. } else {
  2002. len = min(slen(src), destCount - 1);
  2003. }
  2004. #elif ME_WIN_LIKE
  2005. len = MultiByteToWideChar(CP_ACP, 0, src, count, dest, (DWORD) destCount - 1);
  2006. #else
  2007. len = mbstowcs(dest, src, destCount - 1);
  2008. #endif
  2009. if (dest) {
  2010. if (len >= 0) {
  2011. dest[len] = 0;
  2012. }
  2013. } else if (len >= destCount) {
  2014. return -1;
  2015. }
  2016. } else {
  2017. len = 0;
  2018. }
  2019. return len;
  2020. }
  2021. wchar *amtow(char *src, ssize *lenp)
  2022. {
  2023. wchar *dest;
  2024. ssize len;
  2025. len = mtow(NULL, MAXSSIZE, src, -1);
  2026. if (len < 0) {
  2027. return NULL;
  2028. }
  2029. if ((dest = walloc((len + 1) * sizeof(wchar))) != NULL) {
  2030. mtow(dest, len + 1, src, -1);
  2031. }
  2032. if (lenp) {
  2033. *lenp = len;
  2034. }
  2035. return dest;
  2036. }
  2037. PUBLIC char *awtom(wchar *src, ssize *lenp)
  2038. {
  2039. char *dest;
  2040. ssize len;
  2041. len = wtom(NULL, MAXSSIZE, src, -1);
  2042. if (len < 0) {
  2043. return NULL;
  2044. }
  2045. if ((dest = walloc(len + 1)) != 0) {
  2046. wtom(dest, len + 1, src, -1);
  2047. }
  2048. if (lenp) {
  2049. *lenp = len;
  2050. }
  2051. return dest;
  2052. }
  2053. #endif
  2054. /*
  2055. Convert a hex string to an integer
  2056. */
  2057. uint hextoi(char *hexstring)
  2058. {
  2059. char *h;
  2060. uint c, v;
  2061. if (!hexstring) {
  2062. return 0;
  2063. }
  2064. v = 0;
  2065. h = hexstring;
  2066. if (*h == '0' && (*(h+1) == 'x' || *(h+1) == 'X')) {
  2067. h += 2;
  2068. }
  2069. while ((c = (uint)*h++) != 0) {
  2070. if (c >= '0' && c <= '9') {
  2071. c -= '0';
  2072. } else if (c >= 'a' && c <= 'f') {
  2073. c = (c - 'a') + 10;
  2074. } else if (c >= 'A' && c <= 'F') {
  2075. c = (c - 'A') + 10;
  2076. } else {
  2077. break;
  2078. }
  2079. v = (v * 0x10) + c;
  2080. }
  2081. return v;
  2082. }
  2083. PUBLIC char *sclone(char *s)
  2084. {
  2085. char *buf;
  2086. if (s == NULL) {
  2087. s = "";
  2088. }
  2089. if ((buf = walloc(strlen(s) + 1)) != 0) {
  2090. strcpy(buf, s);
  2091. }
  2092. return buf;
  2093. }
  2094. /*
  2095. Clone a sub-string of a specified length. The null is added after the length. The given len can be longer than the
  2096. source string.
  2097. */
  2098. PUBLIC char *snclone(char *str, ssize len)
  2099. {
  2100. char *ptr;
  2101. ssize size, l;
  2102. if (str == 0) {
  2103. str = "";
  2104. }
  2105. l = slen(str);
  2106. len = min(l, len);
  2107. size = len + 1;
  2108. if ((ptr = walloc(size)) != 0) {
  2109. memcpy(ptr, str, len);
  2110. ptr[len] = '\0';
  2111. }
  2112. return ptr;
  2113. }
  2114. PUBLIC bool snumber(cchar *s)
  2115. {
  2116. if (!s) {
  2117. return 0;
  2118. }
  2119. if (*s == '-' || *s == '+') {
  2120. s++;
  2121. }
  2122. return s && *s && strspn(s, "1234567890") == strlen(s);
  2123. }
  2124. /*
  2125. Convert a string to an integer. If the string starts with "0x" or "0X" a hexidecimal conversion is done.
  2126. */
  2127. uint strtoi(char *s)
  2128. {
  2129. if (*s == '0' && (*(s+1) == 'x' || *(s+1) == 'X')) {
  2130. s += 2;
  2131. return hextoi(s);
  2132. }
  2133. return atoi(s);
  2134. }
  2135. PUBLIC int scaselesscmp(char *s1, char *s2)
  2136. {
  2137. if (s1 == 0) {
  2138. return -1;
  2139. } else if (s2 == 0) {
  2140. return 1;
  2141. }
  2142. return sncaselesscmp(s1, s2, max(slen(s1), slen(s2)));
  2143. }
  2144. PUBLIC bool scaselessmatch(char *s1, char *s2)
  2145. {
  2146. return scaselesscmp(s1, s2) == 0;
  2147. }
  2148. PUBLIC bool smatch(char *s1, char *s2)
  2149. {
  2150. return scmp(s1, s2) == 0;
  2151. }
  2152. PUBLIC bool sstarts(cchar *str, cchar *prefix)
  2153. {
  2154. if (str == 0 || prefix == 0) {
  2155. return 0;
  2156. }
  2157. if (strncmp(str, prefix, slen(prefix)) == 0) {
  2158. return 1;
  2159. }
  2160. return 0;
  2161. }
  2162. PUBLIC int scmp(char *s1, char *s2)
  2163. {
  2164. if (s1 == s2) {
  2165. return 0;
  2166. } else if (s1 == 0) {
  2167. return -1;
  2168. } else if (s2 == 0) {
  2169. return 1;
  2170. }
  2171. return sncmp(s1, s2, max(slen(s1), slen(s2)));
  2172. }
  2173. PUBLIC ssize slen(cchar *s)
  2174. {
  2175. return s ? strlen(s) : 0;
  2176. }
  2177. PUBLIC ssize scopy(char *dest, ssize destMax, char *src)
  2178. {
  2179. ssize len;
  2180. assert(src);
  2181. assert(dest);
  2182. assert(0 < dest && destMax < MAXINT);
  2183. len = slen(src);
  2184. if (destMax <= len) {
  2185. return -1;
  2186. }
  2187. strcpy(dest, src);
  2188. return len;
  2189. }
  2190. /*
  2191. This routine copies at most "count" characters from a string. It ensures the result is always null terminated and
  2192. the buffer does not overflow. Returns -1 if the buffer is too small.
  2193. */
  2194. PUBLIC ssize sncopy(char *dest, ssize destMax, char *src, ssize count)
  2195. {
  2196. ssize len;
  2197. assert(dest);
  2198. assert(src);
  2199. assert(src != dest);
  2200. assert(0 <= count && count < MAXINT);
  2201. assert(0 < destMax && destMax < MAXINT);
  2202. // OPT need snlen(src, count);
  2203. len = slen(src);
  2204. len = min(len, count);
  2205. if (destMax <= len) {
  2206. return -1;
  2207. }
  2208. if (len > 0) {
  2209. memcpy(dest, src, len);
  2210. dest[len] = '\0';
  2211. } else {
  2212. *dest = '\0';
  2213. len = 0;
  2214. }
  2215. return len;
  2216. }
  2217. #if KEEP
  2218. /*
  2219. Return the length of a string limited by a given length
  2220. */
  2221. PUBLIC ssize strnlen(char *s, ssize n)
  2222. {
  2223. ssize len;
  2224. len = strlen(s);
  2225. return min(len, n);
  2226. }
  2227. #endif
  2228. /*
  2229. Case sensitive string comparison. Limited by length
  2230. */
  2231. PUBLIC int sncmp(char *s1, char *s2, ssize n)
  2232. {
  2233. int rc;
  2234. assert(0 <= n && n < MAXINT);
  2235. if (s1 == 0 && s2 == 0) {
  2236. return 0;
  2237. } else if (s1 == 0) {
  2238. return -1;
  2239. } else if (s2 == 0) {
  2240. return 1;
  2241. }
  2242. for (rc = 0; n > 0 && *s1 && rc == 0; s1++, s2++, n--) {
  2243. rc = *s1 - *s2;
  2244. }
  2245. if (rc) {
  2246. return (rc > 0) ? 1 : -1;
  2247. } else if (n == 0) {
  2248. return 0;
  2249. } else if (*s1 == '\0' && *s2 == '\0') {
  2250. return 0;
  2251. } else if (*s1 == '\0') {
  2252. return -1;
  2253. } else if (*s2 == '\0') {
  2254. return 1;
  2255. }
  2256. return 0;
  2257. }
  2258. PUBLIC int sncaselesscmp(char *s1, char *s2, ssize n)
  2259. {
  2260. int rc;
  2261. assert(0 <= n && n < MAXINT);
  2262. if (s1 == 0) {
  2263. return -1;
  2264. } else if (s2 == 0) {
  2265. return 1;
  2266. }
  2267. for (rc = 0; n > 0 && *s1 && rc == 0; s1++, s2++, n--) {
  2268. rc = tolower((uchar) *s1) - tolower((uchar) *s2);
  2269. }
  2270. if (rc) {
  2271. return (rc > 0) ? 1 : -1;
  2272. } else if (n == 0) {
  2273. return 0;
  2274. } else if (*s1 == '\0' && *s2 == '\0') {
  2275. return 0;
  2276. } else if (*s1 == '\0') {
  2277. return -1;
  2278. } else if (*s2 == '\0') {
  2279. return 1;
  2280. }
  2281. return 0;
  2282. }
  2283. /*
  2284. Split a string at a delimiter and return the parts.
  2285. This differs from stok in that it never returns null. Also, stok eats leading deliminators, whereas
  2286. ssplit will return an empty string if there are leading deliminators.
  2287. Note: Modifies the original string and returns the string for chaining.
  2288. */
  2289. PUBLIC char *ssplit(char *str, cchar *delim, char **last)
  2290. {
  2291. char *end;
  2292. if (last) {
  2293. *last = "";
  2294. }
  2295. if (str == 0) {
  2296. return "";
  2297. }
  2298. if (delim == 0 || *delim == '\0') {
  2299. return str;
  2300. }
  2301. if ((end = strpbrk(str, delim)) != 0) {
  2302. *end++ = '\0';
  2303. end += strspn(end, delim);
  2304. } else {
  2305. end = "";
  2306. }
  2307. if (last) {
  2308. *last = end;
  2309. }
  2310. return str;
  2311. }
  2312. /*
  2313. Note "str" is modifed as per strtok()
  2314. WARNING: this does not allocate
  2315. */
  2316. PUBLIC char *stok(char *str, char *delim, char **last)
  2317. {
  2318. char *start, *end;
  2319. ssize i;
  2320. start = str ? str : *last;
  2321. if (start == 0) {
  2322. *last = 0;
  2323. return 0;
  2324. }
  2325. i = strspn(start, delim);
  2326. start += i;
  2327. if (*start == '\0') {
  2328. *last = 0;
  2329. return 0;
  2330. }
  2331. end = strpbrk(start, delim);
  2332. if (end) {
  2333. *end++ = '\0';
  2334. i = strspn(end, delim);
  2335. end += i;
  2336. }
  2337. *last = end;
  2338. return start;
  2339. }
  2340. PUBLIC char *strim(char *str, char *set, int where)
  2341. {
  2342. char *s;
  2343. ssize len, i;
  2344. if (str == 0 || set == 0) {
  2345. return 0;
  2346. }
  2347. if (where & WEBS_TRIM_START) {
  2348. i = strspn(str, set);
  2349. } else {
  2350. i = 0;
  2351. }
  2352. s = (char*) &str[i];
  2353. if (where & WEBS_TRIM_END) {
  2354. len = strlen(s);
  2355. while (len > 0 && strspn(&s[len - 1], set) > 0) {
  2356. s[len - 1] = '\0';
  2357. len--;
  2358. }
  2359. }
  2360. return s;
  2361. }
  2362. /*
  2363. Parse the args and return the count of args. If argv is NULL, the args are parsed read-only. If argv is set,
  2364. then the args will be extracted, back-quotes removed and argv will be set to point to all the args.
  2365. NOTE: this routine does not allocate.
  2366. */
  2367. PUBLIC int websParseArgs(char *args, char **argv, int maxArgc)
  2368. {
  2369. char *dest, *src, *start;
  2370. int quote, argc;
  2371. /*
  2372. Example "showColors" red 'light blue' "yellow white" 'Cannot \"render\"'
  2373. Becomes: ["showColors", "red", "light blue", "yellow white", "Cannot \"render\""]
  2374. */
  2375. for (argc = 0, src = args; src && *src != '\0' && argc < maxArgc; argc++) {
  2376. while (isspace((uchar) *src)) {
  2377. src++;
  2378. }
  2379. if (*src == '\0') {
  2380. break;
  2381. }
  2382. start = dest = src;
  2383. if (*src == '"' || *src == '\'') {
  2384. quote = *src;
  2385. src++;
  2386. dest++;
  2387. } else {
  2388. quote = 0;
  2389. }
  2390. if (argv) {
  2391. argv[argc] = src;
  2392. }
  2393. while (*src) {
  2394. if (*src == '\\' && src[1] && (src[1] == '\\' || src[1] == '"' || src[1] == '\'')) {
  2395. src++;
  2396. } else {
  2397. if (quote) {
  2398. if (*src == quote && !(src > start && src[-1] == '\\')) {
  2399. break;
  2400. }
  2401. } else if (*src == ' ') {
  2402. break;
  2403. }
  2404. }
  2405. if (argv) {
  2406. *dest++ = *src;
  2407. }
  2408. src++;
  2409. }
  2410. if (*src != '\0') {
  2411. src++;
  2412. }
  2413. if (argv) {
  2414. *dest++ = '\0';
  2415. }
  2416. }
  2417. return argc;
  2418. }
  2419. #if ME_GOAHEAD_LEGACY
  2420. PUBLIC int fmtValloc(char **sp, int n, char *format, va_list args)
  2421. {
  2422. *sp = sfmtv(format, args);
  2423. return (int) slen(*sp);
  2424. }
  2425. PUBLIC int fmtAlloc(char **sp, int n, char *format, ...)
  2426. {
  2427. va_list args;
  2428. va_start(args, format);
  2429. *sp = sfmtv(format, args);
  2430. va_end(args);
  2431. return (int) slen(*sp);
  2432. }
  2433. #endif
  2434. /*
  2435. Copyright (c) Embedthis Software. All Rights Reserved.
  2436. This software is distributed under commercial and open source licenses.
  2437. You may use the Embedthis GoAhead open source license or you may acquire
  2438. a commercial license from Embedthis Software. You agree to be fully bound
  2439. by the terms of either license. Consult the LICENSE.md distributed with
  2440. this software for full details and other copyrights.
  2441. */