📄 parser.c
字号:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <stdarg.h>#include <string.h>#include <stddef.h>#include <ctype.h>#include "init.h"#include "property_service.h"#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_#include <sys/_system_properties.h>static list_declare(service_list);static list_declare(action_list);static list_declare(action_queue);#define RAW(x...) log_write(6, x)void DUMP(void){#if 0 struct service *svc; struct action *act; struct command *cmd; struct listnode *node; struct listnode *node2; struct socketinfo *si; int n; list_for_each(node, &service_list) { svc = node_to_item(node, struct service, slist); RAW("service %s\n", svc->name); RAW(" class '%s'\n", svc->classname); RAW(" exec"); for (n = 0; n < svc->nargs; n++) { RAW(" '%s'", svc->args[n]); } RAW("\n"); for (si = svc->sockets; si; si = si->next) { RAW(" socket %s %s 0%o\n", si->name, si->type, si->perm); } } list_for_each(node, &action_list) { act = node_to_item(node, struct action, alist); RAW("on %s\n", act->name); list_for_each(node2, &act->commands) { cmd = node_to_item(node2, struct command, clist); RAW(" %p", cmd->func); for (n = 0; n < cmd->nargs; n++) { RAW(" %s", cmd->args[n]); } RAW("\n"); } RAW("\n"); }#endif }#define MAXARGS 64#define T_EOF 0#define T_TEXT 1#define T_NEWLINE 2struct parse_state{ char *ptr; char *text; int line; int nexttoken; void *context; void (*parse_line)(struct parse_state *state, int nargs, char **args); const char *filename;};static void *parse_service(struct parse_state *state, int nargs, char **args);static void parse_line_service(struct parse_state *state, int nargs, char **args);static void *parse_action(struct parse_state *state, int nargs, char **args);static void parse_line_action(struct parse_state *state, int nargs, char **args);void parse_error(struct parse_state *state, const char *fmt, ...){ va_list ap; char buf[128]; int off; snprintf(buf, 128, "%s: %d: ", state->filename, state->line); buf[127] = 0; off = strlen(buf); va_start(ap, fmt); vsnprintf(buf + off, 128 - off, fmt, ap); va_end(ap); buf[127] = 0; ERROR("%s", buf);}#define SECTION 0x01#define COMMAND 0x02#define OPTION 0x04#include "keywords.h"#define KEYWORD(symbol, flags, nargs, func) \ [ K_##symbol ] = { #symbol, func, nargs + 1, flags, },struct { const char *name; int (*func)(int nargs, char **args); unsigned char nargs; unsigned char flags;} keyword_info[KEYWORD_COUNT] = { [ K_UNKNOWN ] = { "unknown", 0, 0, 0 },#include "keywords.h" };#undef KEYWORD#define kw_is(kw, type) (keyword_info[kw].flags & (type))#define kw_name(kw) (keyword_info[kw].name)#define kw_func(kw) (keyword_info[kw].func)#define kw_nargs(kw) (keyword_info[kw].nargs)int lookup_keyword(const char *s){ switch (*s++) { case 'c': if (!strcmp(s, "apability")) return K_capability; if (!strcmp(s, "lass")) return K_class; if (!strcmp(s, "lass_start")) return K_class_start; if (!strcmp(s, "lass_stop")) return K_class_stop; if (!strcmp(s, "onsole")) return K_console; if (!strcmp(s, "hown")) return K_chown; if (!strcmp(s, "hmod")) return K_chmod; if (!strcmp(s, "ritical")) return K_critical; break; case 'd': if (!strcmp(s, "isabled")) return K_disabled; if (!strcmp(s, "omainname")) return K_domainname; if (!strcmp(s, "evice")) return K_device; break; case 'e': if (!strcmp(s, "xec")) return K_exec; if (!strcmp(s, "xport")) return K_export; break; case 'g': if (!strcmp(s, "roup")) return K_group; break; case 'h': if (!strcmp(s, "ostname")) return K_hostname; break; case 'i': if (!strcmp(s, "fup")) return K_ifup; if (!strcmp(s, "nsmod")) return K_insmod; if (!strcmp(s, "mport")) return K_import; break; case 'l': if (!strcmp(s, "oglevel")) return K_loglevel; break; case 'm': if (!strcmp(s, "kdir")) return K_mkdir; if (!strcmp(s, "ount")) return K_mount; break; case 'o': if (!strcmp(s, "n")) return K_on; if (!strcmp(s, "neshot")) return K_oneshot; if (!strcmp(s, "nrestart")) return K_onrestart; break; case 'r': if (!strcmp(s, "estart")) return K_restart; break; case 's': if (!strcmp(s, "ervice")) return K_service; if (!strcmp(s, "etenv")) return K_setenv; if (!strcmp(s, "etkey")) return K_setkey; if (!strcmp(s, "etprop")) return K_setprop; if (!strcmp(s, "etrlimit")) return K_setrlimit; if (!strcmp(s, "ocket")) return K_socket; if (!strcmp(s, "tart")) return K_start; if (!strcmp(s, "top")) return K_stop; if (!strcmp(s, "ymlink")) return K_symlink; break; case 't': if (!strcmp(s, "rigger")) return K_trigger; break; case 'u': if (!strcmp(s, "ser")) return K_user; break; case 'w': if (!strcmp(s, "rite")) return K_write; break; } return K_UNKNOWN;}void parse_line_no_op(struct parse_state *state, int nargs, char **args){}int next_token(struct parse_state *state){ char *x = state->ptr; char *s; if (state->nexttoken) { int t = state->nexttoken; state->nexttoken = 0; return t; } for (;;) { switch (*x) { case 0: state->ptr = x; return T_EOF; case '\n': state->line++; x++; state->ptr = x; return T_NEWLINE; case ' ': case '\t': case '\r': x++; continue; case '#': while (*x && (*x != '\n')) x++; state->line++; state->ptr = x; return T_NEWLINE; default: goto text; } }textdone: state->ptr = x; *s = 0; return T_TEXT;text: state->text = s = x;textresume: for (;;) { switch (*x) { case 0: goto textdone; case ' ': case '\t': case '\r': x++; goto textdone; case '\n': state->nexttoken = T_NEWLINE; x++; goto textdone; case '"': x++; for (;;) { switch (*x) { case 0: /* unterminated quoted thing */ state->ptr = x; return T_EOF; case '"': x++; goto textresume; default: *s++ = *x++; } } break; case '\\': x++; switch (*x) { case 0: goto textdone; case 'n': *s++ = '\n'; break; case 'r': *s++ = '\r'; break; case 't': *s++ = '\t'; break; case '\\': *s++ = '\\'; break; case '\r': /* \ <cr> <lf> -> line continuation */ if (x[1] != '\n') { x++; continue; } case '\n': /* \ <lf> -> line continuation */ state->line++; x++; /* eat any extra whitespace */ while((*x == ' ') || (*x == '\t')) x++; continue; default: /* unknown escape -- just copy */ *s++ = *x++; } continue; default: *s++ = *x++; } } return T_EOF;}void parse_line(int nargs, char **args){ int n; int id = lookup_keyword(args[0]); printf("%s(%d)", args[0], id); for (n = 1; n < nargs; n++) { printf(" '%s'", args[n]); } printf("\n");}void parse_new_section(struct parse_state *state, int kw, int nargs, char **args){ printf("[ %s %s ]\n", args[0], nargs > 1 ? args[1] : ""); switch(kw) { case K_service: state->context = parse_service(state, nargs, args); if (state->context) { state->parse_line = parse_line_service; return; } break; case K_on: state->context = parse_action(state, nargs, args); if (state->context) { state->parse_line = parse_line_action; return; } break; } state->parse_line = parse_line_no_op;}static void parse_config(const char *fn, char *s){ struct parse_state state; char *args[MAXARGS]; int nargs; nargs = 0; state.filename = fn; state.line = 1; state.ptr = s; state.nexttoken = 0; state.parse_line = parse_line_no_op; for (;;) { switch (next_token(&state)) { case T_EOF: state.parse_line(&state, 0, 0); return; case T_NEWLINE: if (nargs) { int kw = lookup_keyword(args[0]); if (kw_is(kw, SECTION)) { state.parse_line(&state, 0, 0); parse_new_section(&state, kw, nargs, args); } else { state.parse_line(&state, nargs, args); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -